【BZOJ 3262】 3262: 陌上花开 (CDQ分治)
3262: 陌上花开
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
HINT
1 <= N <= 100,000, 1 <= K <= 200,000
Source
【分析】
三维偏序。。经典CDQ。。
如此文艺的名字。。
先把属性完全相同的合并,然后三个关键字一起排序,可以避免后影响前的问题。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 100010 8 #define Maxk 200010 9 10 struct node 11 { 12 int a,b,c,sm,ans; 13 }t[Maxn]; 14 15 int mx=0; 16 17 int mymax(int x,int y) {return x>y?x:y;} 18 19 bool cmp(node x,node y) 20 { 21 if(x.a!=y.a) return x.a<y.a; 22 if(x.b!=y.b) return x.b<y.b; 23 return x.c<y.c; 24 } 25 26 bool cmp2(int x,int y) {return (t[x].b==t[y].b)?(x<y):(t[x].b<t[y].b);} 27 28 int c[Maxk],num[Maxn]; 29 void add(int x,int y) 30 { 31 for(int i=x;i<=mx;i+=i&(-i)) c[i]+=y; 32 } 33 34 int query(int x) 35 { 36 int ans=0; 37 for(int i=x;i>=1;i-=i&(-i)) 38 ans+=c[i]; 39 return ans; 40 } 41 42 int nw[Maxn]; 43 void ffind(int l,int r) 44 { 45 if(l==r) return; 46 int mid=(l+r)>>1; 47 nw[0]=0; 48 for(int i=l;i<=r;i++) nw[++nw[0]]=i; 49 sort(nw+1,nw+1+nw[0],cmp2); 50 for(int i=1;i<=nw[0];i++) 51 { 52 if(nw[i]<=mid) add(t[nw[i]].c,t[nw[i]].sm); 53 else 54 { 55 t[nw[i]].ans+=query(t[nw[i]].c); 56 } 57 } 58 for(int i=1;i<=nw[0];i++) if(nw[i]<=mid) add(t[nw[i]].c,-t[nw[i]].sm); 59 ffind(l,mid);ffind(mid+1,r); 60 } 61 62 int main() 63 { 64 int n,k; 65 scanf("%d%d",&n,&k); 66 for(int i=1;i<=n;i++) 67 { 68 scanf("%d%d%d",&t[i].a,&t[i].b,&t[i].c); 69 mx=mymax(mx,t[i].c); 70 t[i].sm=1; 71 } 72 sort(t+1,t+1+n,cmp); 73 int len=1; 74 for(int i=2;i<=n;i++) 75 { 76 if(t[i].a!=t[len].a||t[i].b!=t[len].b||t[i].c!=t[len].c) t[++len]=t[i]; 77 else t[len].sm++; 78 } 79 for(int i=1;i<=len;i++) t[i].ans=0; 80 memset(c,0,sizeof(c)); 81 ffind(1,len); 82 memset(num,0,sizeof(num)); 83 // for(int i=1;i<=n;i++) printf("%d\n",t[i].ans); 84 for(int i=1;i<=len;i++) num[t[i].ans+t[i].sm-1]+=t[i].sm; 85 for(int i=0;i<n;i++) printf("%d\n",num[i]); 86 return 0; 87 }
2017-01-19 09:17:11