三维经典
/* 废话不多看 打一打就懂了 排序不用说 按照a,b,c等级排序 第二维用归并排序 过程中把c的信息放进树状数组里 同时把(l,mid)部分放进树状数组 (mid+1,r)部分求解 一次归并玩后 删除(l,mid) 在树状数组的记录(其实就是清空 不过这样比memset快 因为有相同的坐标 稍微处理一下就行了 */ #include<cstdio> #include<cstring> #include<algorithm> #define mid ((l+r)>>1) using namespace std; const int N=1e5+50; int s[N<<1],ans[N],n,m,res; struct pp {int a,b,c,w,f;} a[N],b[N]; bool cmp(pp a,pp 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; } int lowbit(int x) {return x&-x;} void add(int x,int c) {while(x<=m) s[x]+=c,x+=lowbit(x);} int find(int x) {res=0;while(x) res+=s[x],x-=lowbit(x);return res;} void CDQ(int l,int r) { if(l>=r) return ; CDQ(l,mid),CDQ(mid+1,r); int i=l,j=mid+1,p=l; while(i<=mid&&j<=r) { if(a[i].b<=a[j].b) add(a[i].c,a[i].w),b[p++]=a[i++]; else a[j].f+=find(a[j].c),b[p++]=a[j++]; } while(i<=mid) add(a[i].c,a[i].w),b[p++]=a[i++]; while(j<=r) a[j].f+=find(a[j].c),b[p++]=a[j++]; for(int i=l;i<=mid;i++) add(a[i].c,-a[i].w); // memset(s,0,sizeof(s)); memset果然T飞。。。。。 for(int i=l;i<=r;i++) a[i]=b[i]; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].c),a[i].w=1,a[i].f=0; sort(a+1,a+n+1,cmp); int top=1; for(int i=2;i<=n;i++) // 合并相同点 if(a[i].a==a[top].a&&a[i].b==a[top].b&&a[i].c==a[top].c) a[top].w++; else a[++top]=a[i]; CDQ(1,top); for(int i=1;i<=top;i++) ans[a[i].f+a[i].w-1]+=a[i].w; // 有等于号 所以要加上相同者的数量 for(int i=0;i<n;i++) printf("%d\n",ans[i]); return 0; }

京公网安备 11010502036488号