解题思路
CDQ分治,和简单题的套路一样,一维排序,一维CDQ,一维树状数组,注意要把三者都相同的元素并到一起。数组不要开小了。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int MAXQ = 100005<<2; const int MAXN = 100005; const int MAXK = 200005; inline int rd(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?x:-x; } int n,k,cnt,Num,f[MAXK]; int tot,ans[MAXN]; struct Query{ int a,b,c; int num,val; bool friend operator<(const Query A,const Query B){ if(A.a!=B.a) return A.a<B.a; if(A.b!=B.b) return A.b<B.b; return A.c<B.c; } }q[MAXQ],tmp[MAXQ]; inline bool cmp(Query A,Query B){ if(A.b!=B.b) return A.b<B.b; if(A.c!=B.c) return A.c<B.c; return A.a<B.a; } void add(int x,int y){ for(;x<=k;x+=x&-x) f[x]+=y; } int query(int x){ int ret=0; for(;x;x-=x&-x) ret+=f[x]; return ret; } void Clear(int x){ for(;x<=k;x+=x&-x) f[x]=0; } void cdq(int l,int r){ if(l==r) return; int mid=l+r>>1;cdq(l,mid);cdq(mid+1,r); int L=l,R=mid+1,o=0; while(L<=mid && R<=r){ if(q[L]<q[R]){ add(q[L].c,q[L].num); tmp[++o]=q[L++]; } else{ q[R].val+=query(q[R].c); tmp[++o]=q[R++]; } } while(L<=mid) tmp[++o]=q[L++]; while(R<=r){ q[R].val+=query(q[R].c); tmp[++o]=q[R++]; } for(register int i=l;i<=mid;i++) Clear(q[i].c); for(register int i=1;i<=o;i++) q[i+l-1]=tmp[i]; } int main(){ n=rd(),k=rd(); for(int i=1;i<=n;i++) q[i].a=rd(),q[i].b=rd(),q[i].c=rd(),q[i].num=1; sort(q+1,q+1+n,cmp);cnt=1; for(int i=2;i<=n;i++){ if(q[i].a==q[cnt].a && q[i].b==q[cnt].b && q[i].c==q[cnt].c) q[cnt].num++; else q[++cnt]=q[i]; } // cout<<" "<<endl; // for(int i=1;i<=cnt;i++) // cout<<q[i].a<<" "<<q[i].b<<" "<<q[i].c<<" "<<q[i].num<<endl; cdq(1,cnt); for(int i=1;i<=cnt;i++) ans[q[i].val+q[i].num-1]+=q[i].num; for(int i=0;i<n;i++) printf("%d ",ans[i]); return 0; }