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

Sample Output

3
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 }
View Code

 

posted @ 2019-08-19 15:26  zjxxcn  阅读(142)  评论(0编辑  收藏  举报