经典CDQ分治题,求三维偏序
#include<cstdio>
#include<algorithm>
using namespace std;const int maxn=200000+200;struct Node{
int a,b,c;int num,level;
}node[maxn];bool cmp(Node A,Node B){
if(A.a==B.a&&A.b==B.b) return A.c<B.c;if(A.a==B.a) return A.b<B.b;return A.a<B.a;
}bool cmpcdq(Node A,Node B){
if(A.b==B.b) return A.c<B.c;return A.b<B.b;
}int tree[maxn],color[maxn];
int ans[maxn];
int type;
int n,k;
int tot;inline int lowbit(int x){
return x&(-x);
} void Add(int ind,int v){
while(ind<=k){
if(color[ind]!=type) tree[ind]=0;color[ind]=type;tree[ind]+=v;ind+=lowbit(ind);}
}int getSum(int ind){
int sum=0;while(ind>0){
if(color[ind]==type) sum+=tree[ind];ind-=lowbit(ind);}return sum;
}void CDQ(int l,int r){
if(l==r) return ;int mid=(l+r)>>1;CDQ(l,mid);CDQ(mid+1,r);sort(node+l,node+mid+1,cmpcdq);sort(node+mid+1,node+r+1,cmpcdq);int i=l;int j=mid+1;type++;for(;j<=r;j++){
for(;node[i].b<=node[j].b&&i<=mid;i++) Add(node[i].c,node[i].num);node[j].level+=getSum(node[j].c); }
}int main(){
scanf("%d%d",&n,&k);for(int i=1;i<=n;i++){
int a,b,c;scanf("%d%d%d",&a,&b,&c);node[i]=Node{
a,b,c,1,0};}sort(node+1,node+n+1,cmp);tot=1;for(int i=2;i<=n;i++){
if(node[i].a==node[tot].a&&node[i].b==node[tot].b&&node[i].c==node[tot].c) node[tot].num++;else node[++tot]=node[i];}CDQ(1,tot);for(int i=1;i<=tot;i++) ans[node[i].num+node[i].level-1]+=node[i].num;for(int i=0;i<n;i++) printf("%d\n",ans[i]);
}