[COGS2479 && COGS2639]高维偏序(CDQ分治,bitset)
COGS2479:四维偏序。
CDQ套CDQ
CDQ:对a分治,对b排序,再对a打标记,然后执行CDQ2
CDQ2:对b分治,对c归并排序,对d树状数组。
1 #include<cstdio> 2 #include<algorithm> 3 #define rep(i,l,r) for (int i=l; i<=r; i++) 4 using namespace std; 5 typedef long long ll; 6 7 const int N=50010; 8 int n,ans,c[N]; 9 struct P{ int a,b,c,d; bool flag; }a[N],t1[N],t2[N]; 10 11 void add(int p,int v){ for(;p<=n;p+=p&-p) c[p]+=v;} 12 int sum(int p){ int re=0; for(;p;p-=p&-p) re+=c[p]; return re; } 13 14 void CDQ2(int l,int r){ 15 if(l==r) return; 16 int mid=(l+r)>>1; 17 CDQ2(l,mid); CDQ2(mid+1,r); 18 int i=l,j=mid+1,p=l; 19 P *a=t1,*t=t2; 20 while(i<=mid||j<=r){ 21 if(j>r||(i<=mid&&a[i].c<a[j].c)){ 22 if(a[i].flag) add(a[i].d,1); 23 t[p++]=a[i++]; 24 }else{ 25 if(!a[j].flag) ans+=sum(a[j].d); 26 t[p++]=a[j++]; 27 } 28 } 29 for(int i=l;i<=mid;i++) if(a[i].flag) add(a[i].d,-1); 30 for(int i=l;i<=r;i++) a[i]=t[i]; 31 } 32 33 void CDQ(int l,int r){ 34 if(l==r) return; 35 int mid=(l+r)>>1; 36 CDQ(l,mid);CDQ(mid+1,r); 37 int i=l,j=mid+1,p=l; 38 P *t=t1; 39 while(i<=mid||j<=r){ 40 if(j>r||(i<=mid&&a[i].b<a[j].b)) (t[p++]=a[i++]).flag=1; 41 else (t[p++]=a[j++]).flag=0; 42 } 43 for(int i=l;i<=r;i++) a[i]=t[i]; 44 CDQ2(l,r); 45 } 46 47 int main(){ 48 freopen("partial_order.in","r",stdin); 49 freopen("partial_order.out","w",stdout); 50 scanf("%d",&n); 51 rep(i,1,n) scanf("%d",&a[i].b); 52 rep(i,1,n) scanf("%d",&a[i].c); 53 rep(i,1,n) scanf("%d",&a[i].d),a[i].a=i; 54 CDQ(1,n); printf("%d",ans); 55 return 0; 56 }
COGS2639 7维偏序。
每一维记录前面的比当前这一维小的数个数,最后bitset取&就好了。
分块降低时空复杂度,均为$O(kn\sqrt{n})$。
1 #include <cstdio> 2 #include <cmath> 3 #include <bitset> 4 #include <algorithm> 5 #define rep(i,l,r) for (int i=l; i<=r; i++) 6 using namespace std; 7 typedef long long ll; 8 typedef bitset<40001>bit; 9 10 const int N=40005; 11 int n,k,size,block[N]; 12 13 struct Bitset{ 14 int a[N],lis[N]; 15 bit B[201]; 16 bit get(int p){ 17 p=a[p]; int bp=block[p]; bit ans=B[bp-1]; 18 for(int i=(bp-1)*size+1;i<p;i++) ans.set(lis[i]); 19 return ans; 20 } 21 }d[7]; 22 23 void build(int op){ 24 rep(i,1,n) d[op].lis[d[op].a[i]]=i; 25 bit t; t.reset(); 26 rep(i,1,n){ 27 t.set(d[op].lis[i]); 28 if(i%size==0) d[op].B[i/size]=t; 29 } 30 } 31 32 int main(){ 33 freopen("partial_order_plus.in","r",stdin); 34 freopen("partial_order_plus.out","w",stdout); 35 scanf("%d%d",&n,&k); size=sqrt(n); 36 rep(i,1,n) block[i]=(i-1)/size+1; 37 rep(i,1,n) d[0].a[i]=i; 38 rep(i,1,k) rep(j,1,n) scanf("%d",&d[i].a[j]); 39 rep(i,0,k) build(i); 40 int ans=0; 41 rep(i,1,n){ 42 bit t=d[0].get(i); 43 rep(j,1,k) t&=d[j].get(i); 44 ans+=t.count(); 45 } 46 printf("%d\n",ans); 47 return 0; 48 }
更高维的偏序呢?$O(n^2)$暴力吧。