三维偏序的模板。
当然各种树套树都可以搞,这里用CDQ分治弄一下。
首先利用排序使第一维有序,然后利用cdq函数开始执行类似归并排序的操作,由于左区间的第一维一定小于右区间的第一维,所以我们在归并过程中直接比较第二维,然后利用树状数组维护第三维,使之满足三维偏序,直接统计答案,执行一次cdq操作即可。
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdio> #include<vector> #include<queue> #include<stack> #include<set> #include<map> #define lowbit(x) (x&(-x)) using namespace std; struct Flower{ int a,b,c,w,ans; friend bool operator < (const Flower &x,const Flower &y){ if(x.a==y.a){ if(x.b==y.b) return x.c<y.c; else return x.b<y.b; }else return x.a<y.a; } }q[100500],tmp[100500]; int read(){ int sum=0,f=1;char x=getchar(); while(x<'0'||x>'9'){ if(x=='-') f=-1; x=getchar(); }while(x>='0'&&x<='9'){ sum=(sum<<3)+(sum<<1)+x-'0'; x=getchar(); }return sum*f; } int n,lin,wmz,N,level[100500],t[205000]; bool gv[100500]; void add(int pos,int val){ for(int i=pos;i<=wmz;i+=lowbit(i)) t[i]+=val; } int ask(int pos){ int ans=0; for(int i=pos;i;i-=lowbit(i)) ans+=t[i]; return ans; } void cdq(int l,int r){ if(l==r) return ; int mid=l+r>>1; int i=l,j=mid+1,tot=l; cdq(l,mid);cdq(mid+1,r); while(i<=mid&&j<=r){ if(q[i].b<=q[j].b) tmp[tot++]=q[i++]; else tmp[tot]=q[j++],gv[tot++]=1; } while(i<=mid) tmp[tot++]=q[i++]; while(j<=r) tmp[tot]=q[j++],gv[tot++]=1; /*cout<<endl; for(int i=l;i<=r;i++) cout<<tmp[i].a<<" "<<tmp[i].b<<" "<<tmp[i].c<<endl;*/ for(int i=l;i<=r;i++){ if(gv[i]) tmp[i].ans+=ask(tmp[i].c); else add(tmp[i].c,tmp[i].w); } for(int i=l;i<=r;i++){ if(!gv[i]) add(tmp[i].c,-tmp[i].w); else gv[i]=0; q[i]=tmp[i]; } } int main(){ n=read(); wmz=read(); for(int i=1;i<=n;i++) q[i].a=read(),q[i].b=read(),q[i].c=read(),q[i].w=1; sort(q+1,q+1+n); /* cout<<endl; for(int i=1;i<=n;i++) cout<<q[i].a<<" "<<q[i].b<<" "<<q[i].c<<endl;*/ lin=1; for(int i=2;i<=n;i++) if(q[i].a==q[lin].a&&q[i].b==q[lin].b&&q[i].c==q[lin].c) q[lin].w++; else q[++lin]=q[i]; N=n; n=lin; /* cout<<endl; for(int i=1;i<=n;i++) cout<<q[i].a<<" "<<q[i].b<<" "<<q[i].c<<" "<<q[i].w<<endl;*/ cdq(1,n); for(int i=1;i<=n;i++) level[q[i].ans+q[i].w-1]+=q[i].w; for(int i=0;i<N;i++) printf("%d ",level[i]); return 0; }