CDQ分治
https://blog.csdn.net/wu_tongtong/article/details/78785836
模板:
三维偏序问题。
hdoj5618 Jam's problem again
传送:http://acm.hdu.edu.cn/showproblem.php?pid=5618
题意:求解有对于每一个三元组$<x_i,y_i,z_i>$,有多少个$<x_j,y_j,z_j>$,满足:$x_i>=x_j && y_i>=y_j && z_i>=z_j$。
数据范围:$1 \le N \le 1e5$,$1 \le x,y,z \le 1e5$
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 struct node{ 5 int x,y,z,id; 6 }a[maxn],b[maxn]; 7 int tree[maxn],ans[maxn]; 8 bool cmp(node p,node q){ 9 return p.x<q.x || p.x==q.x && p.y<q.y || p.x==q.x && p.y==q.y && p.z<q.z; 10 } 11 int lowbit(int x){ 12 return x&-x; 13 } 14 void add(int x,int kk){ 15 while (x<maxn){ 16 tree[x]+=kk; 17 x+=lowbit(x); 18 } 19 } 20 int query(int x){ 21 int res=0; 22 while (x>0){ 23 res+=tree[x]; 24 x-=lowbit(x); 25 } 26 return res; 27 } 28 void _clear(int x){ 29 while (x<maxn){ 30 if (tree[x]==0) break; 31 tree[x]=0; 32 x+=lowbit(x); 33 } 34 } 35 void cdq(int l,int r){ 36 if (l==r) return ; 37 int mid=(l+r)>>1; 38 cdq(l,mid); 39 cdq(mid+1,r); 40 int i=l,j=mid+1,k=l; 41 while (i<=mid && j<=r){ 42 if (a[i].y<=a[j].y){ 43 add(a[i].z,1); 44 b[k++]=a[i++]; 45 } 46 else{ 47 ans[a[j].id]+=query(a[j].z); 48 b[k++]=a[j++]; 49 } 50 } 51 while (i<=mid){ 52 add(a[i].z,1); 53 b[k++]=a[i++]; 54 } 55 while (j<=r){ 56 ans[a[j].id]+=query(a[j].z); 57 b[k++]=a[j++]; 58 } 59 for (int i=l;i<=r;i++) 60 _clear(a[i].z),a[i]=b[i]; 61 } 62 int main(){ 63 int t,n; scanf("%d",&t); 64 while(t--){ 65 scanf("%d",&n); 66 for (int i=1;i<=n;i++){ 67 scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); 68 a[i].id=i; ans[i]=0; 69 } 70 sort(a+1,a+1+n,cmp); 71 node tmp={-1,-1,-1,-1};int res=0; 72 for (int i=n;i>=1;i--){ 73 if (tmp.x==a[i].x && tmp.y==a[i].y && tmp.z==a[i].z){ 74 ans[a[i].id]+=res; 75 res++; 76 } 77 else { 78 tmp=a[i]; res=1; 79 } 80 } 81 cdq(1,n); 82 for (int i=1;i<=n;i++) printf("%d\n",ans[i]); 83 } 84 return 0; 85 }