第一维对a排序
第二维归并排序,因为已经按a排过序,在左边和右边对b排序时仍保证左边的a小于右边
第三维树状数组,查询满足前两位偏序关系,且c小于当前数的个数
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> #include<stack> #include<cmath> using namespace std; typedef long long ll; const int maxn = 200010; int n,k,cnt,ans=0; struct Node{ int a,b,c,v,id; }a[maxn],b[maxn],lc[maxn],rc[maxn]; int s[maxn],f[maxn],d[maxn]; void add(int x,int v){ for(int i=x;i<=k;i+=i&(-i)) s[i]+=v; } int sum(int x){ int res=0; for(int i=x;i>0;i-=i&(-i)) res+=s[i]; return res; } void clear(int x){ for(int i=x;i<=k;i+=i&(-i)) s[i]=0; } bool cmpx(Node a,Node b){ return a.a!=b.a?a.a<b.a:a.b!=b.b?a.b<b.b:a.c<b.c; } bool cmpy(Node a,Node b){ return a.b!=b.b?a.b<b.b:a.c<b.c; } void cdq(int l,int r){ if(l==r) return; int mid=(l+r)/2; cdq(l,mid),cdq(mid+1,r); for(int i=l;i<=mid;i++) lc[i]=b[i]; for(int i=mid+1;i<=r;i++) rc[i]=b[i]; sort(lc+l,lc+1+mid,cmpy); sort(rc+mid+1,rc+r+1,cmpy); int p=l,q=mid+1; while(p<=mid&&q<=r){ if(lc[p].b<=rc[q].b){ add(lc[p].c,lc[p].v); ++p; } else{ f[rc[q].id]+=sum(rc[q].c); ++q; } } while(q<=r){ f[rc[q].id]+=sum(rc[q].c); ++q; } for(int i=l;i<=mid;i++){ clear(lc[i].c); } } ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f;} int main(){ n=read(),k=read(); for(int i=1;i<=n;i++){ a[i].a=read(),a[i].b=read(),a[i].c=read(),a[i].id=i; } sort(a+1,a+1+n,cmpx); for(int i=1;i<=n;i++){ if(a[i].a==a[i-1].a&&a[i].b==a[i-1].b&&a[i].c==a[i-1].c){ ++b[cnt].v; }else{ b[++cnt].a=a[i].a,b[cnt].b=a[i].b,b[cnt].c=a[i].c,b[cnt].id=a[i].id; b[cnt].v=1; } } cdq(1,cnt); for(int i=1;i<=cnt;i++){ d[f[b[i].id]+b[i].v-1]+=b[i].v; } for(int i=0;i<=n-1;i++){ printf("%d\n",d[i]); } return 0; }