cdq分治 bzoj 3262 陌上花开 and luogu 3810
Description
有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),用三个整数表示。
现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。
定义一朵花A比另一朵花B要美丽,当且仅Sa>=Sb,Ca>=Cb,Ma>=Mb。
显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。
Input
第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值。
以下N行,每行三个整数si, ci, mi (1 <= si, ci, mi <= K),表示第i朵花的属性
Output
包含N行,分别表示评级为0...N-1的每级花的数量。
Sample Input
10 3
3 3 3
2 3 3
2 3 1
3 1 1
3 1 2
1 3 1
1 1 2
1 2 2
1 3 2
1 2 1
3 3 3
2 3 3
2 3 1
3 1 1
3 1 2
1 3 1
1 1 2
1 2 2
1 3 2
1 2 1
Sample Output
3
1
3
0
1
0
1
0
0
1
1
3
0
1
0
1
0
0
1
cdq入门题, 三维偏序,cdq最好的地方在于可以降一维数据结构。
cdq核心是要考虑左区间对右区间的影响。
这题还有相同的点,需要先提前处理。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int const N=100000+10; 4 struct query{ 5 int x,y,z,id; 6 bool operator < (const query &rhs) const{ 7 if(x!=rhs.x) return x<rhs.x; 8 if(y!=rhs.y) return y<rhs.y; 9 return z<rhs.z; 10 } 11 }q[N],t[N]; 12 int ans[N],n,k,c[N<<1],num[N],cnt[N]; 13 inline int getsum(int x){ 14 int s=0; 15 for(int i=x;i;i-=(i&-i)) 16 s+=c[i]; 17 return s; 18 } 19 void update(int x,int v){ 20 for(int i=x;i<=k;i+=(i&(-i))) 21 c[i]+=v; 22 } 23 void cdq(int l,int r) 24 { 25 if(l==r) return; 26 int mid=(l+r)/2; 27 cdq(l,mid); 28 cdq(mid+1,r); 29 int i=l,j=mid+1,k=l; 30 while (i<=mid && j<=r){ 31 if(q[i].y<=q[j].y) 32 { 33 // if(l==1 && r==7) cout<<getsum(3)<<" 333"<<endl; 34 update(q[i].z,cnt[q[i].id]),t[k++]=q[i++]; 35 } 36 else { 37 ans[q[j].id]+=getsum(q[j].z); 38 if(q[j].x==2 && q[j].y==1 && q[j].z==3){ 39 //for(int k=l;k<=r;k++) 40 // cout<<q[k].x<<" "<<q[k].y<<" "<<q[k].z<<" "<<q[k].id<<"nima"<<" "<<getsum(3)<<i<<" "<<j<<" "<<endl; 41 // cout<<"###"<<q[j].id<<" "<<l<<" "<<r<<" "<<ans[q[j].id]<<endl; 42 } 43 t[k++]=q[j++]; 44 } 45 } 46 while (i<=mid) update(q[i].z,cnt[q[i].id]),t[k++]=q[i++]; 47 while (j<=r) ans[q[j].id]+=getsum(q[j].z),t[k++]=q[j++]; 48 //if(l==5 && r==7) cout<<"#####################"<<getsum(3)<<endl; 49 for(int i=l;i<=mid;i++) update(q[i].z,-cnt[q[i].id]); 50 for(int i=l;i<=r;i++) q[i]=t[i]; 51 // cout<<"end "<<l<<" "<<r<<" "<<getsum(3)<<endl; 52 } 53 int main(){ 54 //freopen("std.out","w",stdout); 55 scanf("%d%d",&n,&k); 56 for(int i=1;i<=n;i++) 57 { 58 scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].z); 59 } 60 sort(q+1,q+n+1); 61 cnt[1]=1; 62 int m=1; 63 for(int i=2;i<=n;i++) 64 if(q[i].x!=q[i-1].x || q[i].y!=q[i-1].y || q[i].z!=q[i-1].z) 65 q[++m]=q[i],cnt[m]=1; 66 else cnt[m]++; 67 //for(int i=1;i<=m;i++) cout<<q[i].x<<" "<<q[i].y<<" "<<q[i].z<<cnt[i]<<endl; 68 for(int i=1;i<=m;i++) q[i].id=i; 69 // cout<<getsum(3)<<"woma"<<endl; 70 cdq(1,m); 71 //for(int i=1;i<=m;i++) 72 // cout<<q[i].x<<" "<<q[i].y<<" "<<q[i].z<<" "<<ans[q[i].id]<<" "<<cnt[q[i].id]<<endl; 73 for(int i=1;i<=m;i++){ 74 num[ans[i]+cnt[i]-1]+=cnt[i]; 75 // cout<<ans[i]<<" "<<cnt[i]<<endl; 76 } 77 for(int i=0;i<n;i++) 78 printf("%d\n",num[i]); 79 return 0; 80 }