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

 

2017-01-19 09:17:11

posted @ 2017-01-19 09:11  konjak魔芋  阅读(269)  评论(0编辑  收藏  举报