P3810 【模板】三维偏序(陌上花开)(bitset)

· · 题解

提供一篇 bitset 的题解。

bitset 可以用来求解高维偏序问题,记 m 为维数,则时间复杂度为 O(\dfrac{n^2m}{w})

n 个 bitset,b_{i,j}=1 表示 j 每一维都不超过 i。初始化所有 b_{i,j}=1

先枚举每一维,然后对所有数按这一维排序。

开一个新的 bitset s,按这一维从小到大处理所有数,处理到 is_j=1 表示当前维 j 不超过 i

每次 `b[i]&=s` 即可。 $100000$ 的 bitset 开不下,要用分组 bitset。 就是将点分为若干组,每组 $B$ 个,每次只求出这 $B$ 个点对应的 bitset,这样只需要开 $B$ 个 bitset。 可能略微卡常。 [AC 提交记录](https://www.luogu.com.cn/record/51314650) ```cpp #include<bits/stdc++.h> using namespace std; const int N=1e5+3; int p[3][N],a[3][N],w[N]; bitset<N>b[9999],s; int main(){ int*tp,*ta,n,l,r,i,j,k,o; for(i=1,scanf("%d%*d",&n);i<=n;++i)for(j=0;j<3;++j)scanf("%d",a[j]+i),p[j][i]=i; for(i=0;i<3;++i)sort(p[i]+1,p[i]+n+1,[=](int x,int y){return a[i][x]<a[i][y];});//按每一维排序 for(l=1;l<=n;l=r+1){//分组bitset,每组9991个 for(i=l,r=min(l+9991,n);i<=r;++i)b[i-l].set(); for(i=0;i<3;++i)for(tp=p[i],ta=a[i],s.reset(),j=k=1;j<=n;++j){ for(o=tp[j];k<=n&&ta[tp[k]]<=ta[o];)s[tp[k++]]=1; if(l<=o&&o<=r)b[o-l]&=s; } for(i=l;i<=r;++i)++w[b[i-l].count()]; } for(i=1;i<=n;++i)printf("%d\n",w[i]); return 0; } ```