【BZOJ 3262三维偏序】陌上花开
【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
Source
CDQ分治,树套树
思路{
CDQ分治维护三维偏序,第一维sort即可,第二维分治即可,第三维套树状数组求解;
!:对于细节处理要注意!在分治时原先的树状数组记录的由于y的情况不同会有误!
所以要多一个数组记录。
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<queue> 7 #include<ctime> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 #define MAXX 1000010 12 #define lowbit(k) k&-k 13 using namespace std; 14 struct f{ 15 int x,y,z,num,ans; 16 }e[MAXX*2]; 17 int fa[MAXX*2],tree[MAXX*2],now,n,k,anss[MAXX*2]; 18 // shuzhuangshuzu 19 int sum(int p){ 20 int num=0; 21 for(int k=p;k;k-=lowbit(k)) 22 if(fa[k]==now)num+=tree[k]; 23 return num; 24 } 25 void add(int p,int num){ 26 for(int k=p;k<MAXX;k+=lowbit(k)){ 27 if(fa[k]!=now)tree[k]=0;//yi jing ji suan guo 28 fa[k]=now;tree[k]+=num; 29 } 30 } 31 // sort!!!!!! 32 bool Comp(const f & a,const f & b){ 33 if(a.y==b.y)return a.z<a.z; 34 return a.y<b.y; 35 } 36 bool comp(const f & a,const f & b){ 37 if(a.x==b.x){ 38 if(a.y==b.y)return a.z<b.z; 39 return a.y<b.y; 40 } 41 return a.x<b.x; 42 } 43 // CDQ fenzhi!! 44 void CDQ(int l,int r){ 45 if(l>=r)return; 46 int mid=(l+r)>>1; 47 CDQ(l,mid),CDQ(mid+1,r); 48 sort(e+l,e+mid+1,Comp),sort(e+mid+1,e+r+1,Comp);now++;int i,j; 49 for(j=mid+1,i=l;j<=r;++j){ 50 for(;e[i].y<=e[j].y&&i<=mid;++i)add(e[i].z,e[i].num); 51 e[j].ans+=sum(e[j].z); 52 } 53 } 54 int main(){ 55 scanf("%d%d",&n,&k);int nn=1; 56 for(int i=1;i<=n;++i)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z),e[i].num++; 57 sort(e+1,e+n+1,comp); 58 for(int i=2;i<=n;++i) 59 if(e[i].x!=e[nn].x||e[i].y!=e[nn].y||e[i].z!=e[nn].z)e[++nn]=e[i]; 60 else e[nn].num++; 61 CDQ(1,nn); 62 for(int i=1;i<=nn;++i)anss[e[i].ans+e[i].num-1]+=e[i].num; 63 for(int i=0;i<n;++i)printf("%d\n",anss[i]); 64 return 0; 65 }