1. 程式人生 > >bzoj3262陌上花開 cdq分治

bzoj3262陌上花開 cdq分治

mil scrip search for ++i int desc 排序 ref

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