陌上花开
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
三维偏序,第一维排序,然后第二维用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 }