luogu 3810
https://www.luogu.org/problemnew/show/3810
CDQ分治棵题
第一维 排序
第二维 CDQ分治
第三位 树状数组维护
#include<stdio.h> #include<algorithm> #define FOR(i,s,t) for(register int i=s;i<=t;++i) using std::sort; const int N=100011; struct point{ int x,y,z,sum,cnt; inline bool operator ==(const point &B)const{ return x==B.x&&y==B.y&&z==B.z; } inline bool operator <(const point &B)const{ if(x!=B.x)return x<B.x; if(y!=B.y)return y<B.y; return z<B.z; } inline bool operator >(const point &B)const{ if(y!=B.y)return y<B.y; return z<=B.z; } }t[N],a[N]; int n,k; int tr[N<<1],ans[N<<1]; inline void add(int p,int v){ for(;p<=k;p+=p&(-p))tr[p]+=v; } inline int query(int p){ int ret=0; for(;p;p-=p&(-p))ret+=tr[p]; return ret; } inline void del(int p){ for(;p<=k;p+=p&(-p)) if(tr[p])tr[p]=0; else break; } inline void cdq(int l,int r){ if(l==r)return; int mid=(l+r)>>1; int idx1=l,idx2=mid+1; cdq(l,mid);cdq(mid+1,r); FOR(i,l,r){ if(idx2>r||(idx1<=mid&&a[idx1]>a[idx2])){ t[i]=a[idx1++]; add(t[i].z,t[i].cnt); } else{ t[i]=a[idx2++]; t[i].sum+=query(t[i].z); } } FOR(i,l,r){ a[i]=t[i]; del(a[i].z); } return; } int main(){ scanf("%d%d",&n,&k); FOR(i,1,n)scanf("%d%d%d",&t[i].x,&t[i].y,&t[i].z); sort(t+1,t+n+1); register int head=1,m=0,tail=0; while(head<=n){ tail=head+1; while(tail<=n&&t[head]==t[tail])++tail; a[++m]=t[head];a[m].cnt=tail-head; head=tail; } cdq(1,m); FOR(i,1,m) ans[a[i].sum+a[i].cnt]+=a[i].cnt; FOR(i,1,n) printf("%d\n",ans[i]); return 0; }