CDQ分治
首先按a排序,分成两段后再分别对两段按b排序,这样就保证了w[x2].a>=w[x1].a,消去一维
按b排序后找到w[x2].b>=w[x1].b的同时满足w[x2].c>=w[x1].c的值
按b排序后有单调性,所以b可以在O(n)时间,对于c,每找到一个w[x1]满足b的条件,则在树状数组中+1
w[x2].ans+=query(w[x2].c)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 struct Node 7 { 8 int a,b,c,cnt,ans; 9 }w[100001]; 10 int m,n,c[2000001],ans,f[100001]; 11 bool cmp2(Node a,Node b) 12 { 13 if (a.b==b.b) 14 return a.c<b.c; 15 else return a.b<b.b; 16 } 17 bool cmp1(Node a,Node b) 18 { 19 if (a.a==b.a) 20 return cmp2(a,b); 21 else return a.a<b.a; 22 } 23 void add(int x,int d) 24 { 25 while (x<=m) 26 { 27 c[x]+=d; 28 x+=(x&(-x)); 29 } 30 } 31 int query(int x) 32 {int s=0; 33 while (x) 34 { 35 s+=c[x]; 36 x-=(x&(-x)); 37 } 38 return s; 39 } 40 void cdq(int l,int r) 41 {int r1,r2; 42 int mid=(l+r)/2; 43 if (l==r) 44 return; 45 cdq(l,mid);cdq(mid+1,r); 46 sort(w+l,w+mid+1,cmp2); 47 sort(w+mid+1,w+r+1,cmp2); 48 r1=l;r2=mid+1; 49 while (r2<=r) 50 { 51 while (r1<=mid&&w[r1].b<=w[r2].b) 52 add(w[r1].c,w[r1].cnt),r1++; 53 w[r2].ans+=query(w[r2].c); 54 r2++; 55 } 56 for (int i=l;i<=r1-1;i++) 57 add(w[i].c,-w[i].cnt); 58 } 59 int main() 60 {int i,j,num=0; 61 cin>>n>>m; 62 for (i=1;i<=n;i++) 63 { 64 scanf("%d%d%d",&w[i].a,&w[i].b,&w[i].c); 65 w[i].cnt=1; 66 } 67 sort(w+1,w+n+1,cmp1); 68 for (i=1;i<=n;i++) 69 { 70 int k=i+1; 71 while (w[i].a==w[k].a&&w[i].b==w[k].b&&w[i].c==w[k].c) 72 k++; 73 num++; 74 k--; 75 w[i].cnt+=k-i; 76 w[num]=w[i]; 77 i=k; 78 } 79 cdq(1,num); 80 for (i=1;i<=num;i++) 81 f[w[i].ans+w[i].cnt-1]+=w[i].cnt; 82 for (i=0;i<n;i++) 83 printf("%d\n",f[i]); 84 }
时间: 2024-12-26 16:44:15