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分治很好的模板。
运用了线段树/树状数组扫描线的思想。
或者说是离线解题时的控制端点动态更新。
动态处理问题获得解还是非常神的思路。
相当于将解集拆分成若干份,每份使用动态统计。
换句话说,就是将一定范围内的数据配对时间复杂度降低。
注意要撤销操作。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 struct pnt{ 6 int x,y,z,f,w; 7 bool friend operator == (pnt a,pnt b) 8 { 9 return a.x==b.x&&a.y==b.y&&a.z==b.z; 10 } 11 bool friend operator != (pnt a,pnt b) 12 { 13 return !(a.x==b.x&&a.y==b.y&&a.z==b.z); 14 } 15 }p[1000001],q[1000001]; 16 int n,k; 17 int cnt; 18 int d[1000001]; 19 int line[1000001]; 20 int has[1000001]; 21 int lowbit(int x) 22 { 23 return x&(-x); 24 } 25 bool cmx(pnt a,pnt b) 26 { 27 if(a.x==b.x&&a.y==b.y) 28 return a.z<b.z; 29 if(a.x==b.x) 30 return a.y<b.y; 31 return a.x<b.x; 32 } 33 bool cmy(pnt a,pnt b) 34 { 35 if(a.x==b.x&&a.y==b.y) 36 return a.z<b.z; 37 if(a.y==b.y) 38 return a.x<b.x; 39 return a.y<b.y; 40 } 41 void add(int p,int v) 42 { 43 while(p<=k) 44 { 45 line[p]+=v; 46 p+=lowbit(p); 47 } 48 return ; 49 } 50 int ask(int p) 51 { 52 int ans=0; 53 while(p) 54 { 55 ans+=line[p]; 56 p-=lowbit(p); 57 } 58 return ans; 59 } 60 void wrk(int l,int r) 61 { 62 int m=(l+r)>>1; 63 sort(p+l,p+m+1,cmy); 64 sort(p+m+1,p+r+1,cmy); 65 int tmp=-1; 66 for(int i=l,j=m+1;j<=r;j++) 67 { 68 for(;i<=m&&p[i].y<=p[j].y;i++) 69 { 70 add(p[i].z,p[i].w); 71 tmp=i; 72 } 73 p[j].f+=ask(p[j].z); 74 } 75 for(int i=l;i<=tmp;i++) 76 add(p[i].z,-p[i].w); 77 } 78 void cdq(int l,int r) 79 { 80 if(l==r) 81 return ; 82 int m=(l+r)>>1; 83 cdq(l,m); 84 cdq(m+1,r); 85 wrk(l,r); 86 } 87 int main() 88 { 89 scanf("%d%d",&n,&k); 90 for(int i=1;i<=n;i++) 91 scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].z); 92 sort(q+1,q+n+1,cmx); 93 int wgt=0; 94 for(int i=1;i<=n;i++) 95 { 96 wgt++; 97 if(q[i]!=q[i+1]) 98 { 99 p[++cnt]=q[i]; 100 p[cnt].w=wgt; 101 wgt=0; 102 } 103 } 104 swap(cnt,n); 105 cdq(1,n); 106 for(int i=1;i<=n;i++) 107 has[p[i].f+p[i].w-1]+=p[i].w; 108 for(int i=0;i<cnt;i++) 109 printf("%d ",has[i]); 110 return 0; 111 }