本质是一个三维偏序,一位排序后cdq分治,一维在子函数里排序,一维用树状数组维护。
把三维相等的合并到一个里面。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #define N 100005 6 using namespace std; 7 int n,k,m; 8 struct node 9 { 10 int x,y,z,num,op; 11 int yuan; 12 bool operator == (const node &b) 13 { 14 return x==b.x&&y==b.y&&z==b.z; 15 } 16 }a[N],b[N]; 17 int shan[N]; 18 int ans[N]; 19 bool cmp1(node aa,node bb) 20 { 21 if(aa.num==0)return 0; 22 if(bb.num==0)return 1; 23 if(aa.x!=bb.x)return aa.x<bb.x; 24 if(aa.y!=bb.y)return aa.y<bb.y; 25 if(aa.z!=bb.z)return aa.z<bb.z; 26 27 } 28 bool cmp2(node aa,node bb) 29 { 30 if(aa.y!=bb.y)return aa.y<bb.y; 31 return aa.op<bb.op; 32 } 33 int c[200005]; 34 void add(int x,int y) 35 { 36 for(int i=x;i<=k;i+=(i&(-i)))c[i]+=y; 37 } 38 int qur(int x) 39 { 40 int now=0; 41 for(int i=x;i;i-=(i&(-i)))now+=c[i]; 42 return now; 43 } 44 void solve(int l,int r) 45 { 46 if(l==r)return ; 47 int mid=(l+r)>>1; 48 solve(l,mid);solve(mid+1,r); 49 int cnt=0; 50 for(int i=l;i<=mid;i++) 51 { 52 b[++cnt]=a[i]; 53 b[cnt].op=1; 54 } 55 for(int i=mid+1;i<=r;i++) 56 { 57 b[++cnt]=a[i]; 58 b[cnt].op=2; 59 } 60 sort(b+1,b+cnt+1,cmp2); 61 for(int i=1;i<=cnt;i++) 62 { 63 if(b[i].op==1)add(b[i].z,b[i].num); 64 else ans[b[i].yuan]+=qur(b[i].z); 65 } 66 for(int i=1;i<=cnt;i++)if(b[i].op==1)add(b[i].z,-b[i].num); 67 } 68 int zui[N]; 69 int main() 70 { 71 scanf("%d%d",&n,&k);m=n; 72 for(int i=1;i<=n;i++) 73 { 74 scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); 75 a[i].num=1; 76 } 77 sort(a+1,a+n+1,cmp1); 78 for(int i=1;i<=n;i++) 79 { 80 if(a[i]==a[i-1]) 81 { 82 a[shan[i-1]].num++; 83 shan[i]=shan[i-1]; 84 a[i].num--; 85 } 86 else shan[i]=i; 87 } 88 sort(a+1,a+n+1,cmp1); 89 while(a[n].num==0)n--; 90 for(int i=1;i<=n;i++)a[i].yuan=i; 91 solve(1,n); 92 for(int i=1;i<=n;i++)zui[ans[a[i].yuan]+a[i].num-1]+=a[i].num; 93 for(int i=0;i<=m-1;i++)printf("%d ",zui[i]); 94 return 0; 95 }