bzoj3262陌上花开 cdq分治

Posted wsy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3262陌上花开 cdq分治相关的知识,希望对你有一定的参考价值。

3262: 陌上花开

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 2794  Solved: 1250
[Submit][Status][Discuss]

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分治

 

三维偏序 -最裸的cdq分治
首先把所有元素按照x排序,然后进行cdq分治

在分治时,总是由分治左区间向右区间转移答案,可以保证转移的x满足条件
按照y排序再转移,保证y有序
树状数组维护z,保证z有序

由于分治是层层递归下去的,所以每个点一定都会计算完它的前缀贡献的答案

另外,cdq分治的核心思想是:先处理左区间,再处理左区间对右区间贡献的答案,最后处理右区间
但对于这个题,可以先左再右,最后左向右贡献答案

 1 #include<bits/stdc++.h>
 2 #define N 100005
 3 using namespace std;
 4 int n,m,pa,pb,acnt,bcnt,tot,cnt[N],pos[N],c[N<<1];
 5 struct info{int x,y,z,id,ans;}q[N],a[N],b[N];
 6 bool cmp1(info a,info b){
 7     if(a.x==b.x){
 8         if(a.y==b.y)return a.z<b.z;
 9         return a.y<b.y;
10     }
11     return a.x<b.x;
12 }
13 bool cmp2(info a,info b){return a.y<b.y;}
14 void add(int p,int v){
15     while(p<=m){
16         c[p]+=v;
17         p+=p&-p;
18     }
19 }
20 int query(int p){
21     int ret=0;
22     while(p){
23         ret+=c[p];
24         p-=p&-p;
25     }
26     return ret;
27 }
28 void cdq(int l,int r){
29     if(l>=r)return;
30     int mid=(l+r)>>1;
31     cdq(l,mid);
32     acnt=bcnt=0;
33     for(int i=l;i<=mid;++i)a[++acnt]=q[i];
34     for(int i=mid+1;i<=r;++i)b[++bcnt]=q[i];
35     sort(a+1,a+1+acnt,cmp2);
36     sort(b+1,b+1+bcnt,cmp2);
37     pa=pb=1;tot=0;
38     while(pb<=bcnt){
39         while(pa<=acnt&&a[pa].y<=b[pb].y){
40             add(a[pa].z,1);
41             pos[++tot]=a[pa].z;
42             ++pa;
43         }
44         q[b[pb].id].ans+=query(b[pb].z);
45         ++pb;
46     }
47     for(int i=1;i<=tot;++i)add(pos[i],-1);
48     cdq(mid+1,r);
49 }
50 int main(){
51     scanf("%d%d",&n,&m);
52     for(int i=1;i<=n;++i)
53     scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].z);
54     sort(q+1,q+1+n,cmp1);
55     for(int i=1;i<=n;++i)q[i].id=i;
56     cdq(1,n);
57     for(int i=n;i;--i)
58     if(q[i].x==q[i+1].x&&q[i].y==q[i+1].y&&q[i].z==q[i+1].z)
59     q[i].ans=max(q[i].ans,q[i+1].ans);
60     for(int i=1;i<=n;++i)++cnt[q[i].ans];
61     for(int i=0;i<n;++i)printf("%d\n",cnt[i]);
62     return 0;
63 }

 

以上是关于bzoj3262陌上花开 cdq分治的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3262: 陌上花开 cdq分治 树状数组

bzoj 3262: 陌上花开 -- CDQ分治

bzoj 3262 陌上花开 CDQ分治

Luogu 3810 & BZOJ 3262 陌上花开/三维偏序 | CDQ分治

BZOJ3262陌上花开 CDQ分治_BIT+Treap

cdq分治入门--BZOJ3262: 陌上花开