首页 > 代码库 > 陌上花开

陌上花开

P2433 - 【BZOJ 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

 

 

<style>pre.cjk { font-family: "Droid Sans Fallback", monospace } p { margin-bottom: 0.25cm; line-height: 120% } a:link { }</style>
三维偏序,第一维排序,然后第二维用CDQ分治:
算法流程:
先从中间二分,把左边和右边分别按第二维排序,
这时第二维是有序的了,第一维并不是有序的,但左区间的都会比右区间的小,
这时就可以搞两个指针分别指向这两个区间,并且第三维用树状数组维护,
这样乱搞一下可以维护三维偏序。
 1 #include<set>
 2 #include<map>
 3 #include<queue>
 4 #include<stack>
 5 #include<ctime>
 6 #include<cmath>
 7 #include<string>
 8 #include<vector>
 9 #include<cstdio>
10 #include<cstdlib>
11 #include<cstring>
12 #include<iostream>
13 #include<algorithm>
14 #define maxn 200010
15 using namespace std;
16 struct data{
17   int a,b,c,lev,num;
18 }f[maxn];
19 int co[maxn],tree[maxn],LOL=0,ans[maxn];
20 int lowbit(int x){return x&(-x);} 
21 bool cmp1(const data &a,const data &b){
22   if(a.a!=b.a) return a.a<b.a;
23   else{
24     if(a.b!=b.b) return a.b<b.b;
25     else return a.c<b.c;
26   }
27 }
28 bool cmp2(const data &a,const data &b){
29   if(a.b!=b.b) return a.b<b.b;
30   else return a.c<b.c;
31 }
32 void add(int p,int v){
33   for(int i=p;i<maxn;i+=lowbit(i)){
34     if(co[i]!=LOL) tree[i]=0;
35     co[i]=LOL;
36     tree[i]+=v;
37   }
38 }
39 int find(int p){
40   int ret=0;
41   for(int i=p;i;i-=lowbit(i))
42     if(co[i]==LOL)
43       ret+=tree[i];
44   return ret;
45 }
46 void QAQ(int l,int r){
47   if(l==r) return;
48   int mid=(l+r)>>1;
49   QAQ(l,mid),QAQ(mid+1,r);
50   sort(f+l,f+mid+1,cmp2);
51   sort(f+mid+1,f+r+1,cmp2);
52   LOL++;
53   for(int j=mid+1,i=l;j<=r;j++){
54     for(;f[i].b<=f[j].b&&i<=mid;i++)
55       add(f[i].c,f[i].num);
56     f[j].lev+=find(f[j].c);
57   }
58 }
59 int main()
60 {
61   freopen("!.in","r",stdin);
62   freopen("!.out","w",stdout);
63   int n,m,tot=0;
64   scanf("%d%d",&n,&m);
65   for(int i=1;i<=n;i++)
66     scanf("%d%d%d",&f[i].a,&f[i].b,&f[i].c),f[i].num++;
67   sort(f+1,f+n+1,cmp1);
68   for(int i=1;i<=n;i++){
69     if(i!=1 && f[i-1].a==f[i].a && f[i-1].b==f[i].b && f[i-1].c==f[i].c) f[tot].num++;
70     else f[++tot].a=f[i].a,f[tot].b=f[i].b,f[tot].c=f[i].c,f[tot].lev=f[i].lev,f[tot].num=f[i].num;
71   }
72   QAQ(1,tot);
73   for(int i=1;i<=tot;i++)
74     ans[f[i].lev+f[i].num-1]+=f[i].num;
75   for(int i=0;i<n;i++)
76     printf("%d\n",ans[i]);
77   return 0;
78 }

 

 

陌上花开