大早上的做了一道三维数点一道五位数点,神清气爽!
先给一维排序,变成一个奇怪的动态的二维数点(相当于有一个扫描面扫过去,导致一系列的加点和询问)
然后cdq分治,再变回静态,考虑前半段对后半段的影响
这时对第二维排序,又变成动态一维数点
树状数组屠之
(不妨再cdq一次变成零维数点,也就是询问一个询问之前有几次修改)(手动滑稽)
另外因为x y z都相同时互相产生影响,特判掉
来上个又臭又长的代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 struct t 4 { 5 int x,y,z,num,ans; 6 } a[100001],b[100001]; 7 int tr[200001],ans[100001]; 8 int n,m; 9 bool comx(t a,t b) 10 { 11 return (a.x<b.x)||(a.x==b.x &&(a.y<b.y || (a.y==b.y &&a.z<b.z))); 12 } 13 bool same(t a,t b) 14 { 15 return (a.x==b.x && a.y==b.y && a.z==b.z); 16 } 17 void add(int x,int y) 18 { 19 while(x<=m) 20 tr[x]+=y,x+=x&-x; 21 } 22 int que(int x) 23 { 24 int ans=0; 25 while(x) 26 ans+=tr[x],x-=x&-x; 27 return ans; 28 } 29 void cdq(int l,int r) 30 { 31 if(l==r) 32 return; 33 int mid=l+r>>1; 34 cdq(l,mid);cdq(mid+1,r); 35 for(int i=l,j=l,k=mid+1;i<=r;i++) 36 if(j<=mid &&(k>r || a[j].y<=a[k].y)) b[i]=a[j++]; 37 else b[i]=a[k++]; 38 for(int i=l;i<=r;i++) 39 { 40 a[i]=b[i]; 41 if(a[i].num<=mid) 42 add(a[i].z,1); 43 else 44 a[i].ans+=que(a[i].z); 45 } 46 for(int i=l;i<=r;i++) 47 if(a[i].num<=mid) 48 add(a[i].z,-1); 49 } 50 int main() 51 { 52 scanf("%d%d",&n,&m); 53 for(int i=1;i<=n;i++) 54 scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); 55 sort(a+1,a+n+1,comx); 56 t tem;int te=1; 57 for(int i=n;i>=1;i--) 58 if(same(tem,a[i])) a[i].ans+=te,++te; 59 else tem=a[i],te=1; 60 // puts(""); 61 // for(int i=1;i<=n;i++) 62 // printf("%d %d %d ",a[i].x,a[i].y,a[i].z); 63 for(int i=1;i<=n;i++) 64 a[i].num=i; 65 cdq(1,n); 66 // for(int i=1;i<=n;i++) 67 // printf("%d %d %d %d ",a[i].x,a[i].y,a[i].z,a[i].ans); 68 for(int i=1;i<=n;i++) 69 ++ans[a[i].ans]; 70 for(int i=0;i<n;i++) 71 printf("%d ",ans[i]); 72 return 0; 73 }