bzoj3262: 陌上花开
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #define maxn 100005 7 #define maxk 200005 8 using namespace std; 9 10 int n,k,m,sum[maxk],ans[maxn],sum_[maxn],ans_[maxn]; 11 struct date{ 12 int x,y,z; 13 }fl[maxn]; 14 struct note{ 15 int y,z,sum,id; 16 }qs[maxn]; 17 18 bool comp1(date x,date y){ 19 if (x.x!=y.x) return x.x<y.x; 20 if (x.y!=y.y) return x.y<y.y; 21 return x.z<y.z; 22 } 23 24 bool comp2(note x,note y){ 25 if (x.y==y.y) return x.z<y.z; 26 return x.y<y.y; 27 } 28 29 int lowbit(int x){ 30 return x&(-x); 31 } 32 33 void add(int x,int y){ 34 for (int i=x;i<=k;i+=lowbit(i)) sum[i]+=y; 35 } 36 37 int query(int x){ 38 int temp=0; 39 for (int i=x;i>0;i-=lowbit(i)){ 40 temp+=sum[i]; 41 } 42 return temp; 43 } 44 45 void cdq_solve(int l,int r){ 46 if (l==r) return; 47 int mid=(l+r)/2; 48 cdq_solve(l,mid),cdq_solve(mid+1,r); 49 sort(qs+l,qs+mid+1,comp2),sort(qs+mid+1,qs+r+1,comp2); 50 int i=l,j=mid+1,temp=0; 51 while (j<=r){ 52 if (i<=mid&&qs[i].y<=qs[j].y) add(qs[i].z,qs[i].sum),i++,temp=i-1; 53 else ans_[qs[j].id]+=query(qs[j].z),j++; 54 } 55 for (int i=l;i<=temp;i++) add(qs[i].z,-qs[i].sum); 56 } 57 58 int main(){ 59 scanf("%d%d",&n,&k),m=0; 60 for (int i=1;i<=n;i++) scanf("%d%d%d",&fl[i].x,&fl[i].y,&fl[i].z); 61 sort(fl+1,fl+n+1,comp1); 62 // for (int i=1;i<=n;i++) printf("%d %d %d\n",fl[i].x,fl[i].y,fl[i].z); 63 memset(sum,0,sizeof(sum)); 64 memset(ans,0,sizeof(ans)); 65 memset(ans_,0,sizeof(ans_)); 66 for (int i=1;i<=n;i++){ 67 if (fl[i].x==fl[i-1].x&&fl[i].y==fl[i-1].y&&fl[i].z==fl[i-1].z){ 68 sum_[m]=++qs[m].sum; 69 }else{ 70 qs[++m].sum=1,qs[m].y=fl[i].y,qs[m].z=fl[i].z,qs[m].id=m; 71 sum_[m]=qs[m].sum; 72 } 73 } 74 cdq_solve(1,m); 75 for (int i=1;i<=m;i++) ans[ans_[i]+sum_[i]-1]+=sum_[i]; 76 for (int i=0;i<n;i++) printf("%d\n",ans[i]); 77 return 0; 78 }
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3262
题目大意:有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),又三个整数表示。现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb。显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。
输入格式:第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值。
以下N行,每行三个整数si, ci, mi (1 <= si, ci, mi <= K),表示第i朵花的属性。
输出格式:包含N行,分别表示评级为0...N-1的每级花的数量。
做法:三维,据说可以用树套树来写(这个以后再尝试写一发),然后这题正解是传统的cdq分治+排序+树状数组,设花的三个属性为x,y,z,我们将花按x为第一关键字,y为第二关键字,z为第三关键字排序,将属性完全相同的缩成一朵花即可,同时维护sum数组,即属形为(x,y,z)的个数,所以在维护树状数组的时候不能+1,而应该+sum[x]。排序后,后面的花只可能会被前面的花所影响,因为在该花后面的花x都比该花大,我们便能想到用cdq分治。
想到这点后,对于合并两个区间信息的问题,我们考虑两个区间分别按y坐标排序,依次第一个区间中的花将z坐标加入树状数组,并及时维护第二个区间中的花的答案,这过程用两个指针维护即可。
cdq分治+树状数组