NEUOJ 1702 撩妹全靠魅力值 (三维偏序)
题目链接:http://acm.neu.edu.cn/hustoj/problem.php?id=1702
题目大意:就是问每个人三个属性同时不低于另外几个人。。。。人不分先后
经典的三维偏序问题
解题思路:CDQ分治练手题
1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 int const MAX_Z=100000+5; 8 int const MAX_N=100000+5; 9 struct Ope{ 10 int x,y,z; 11 int ty,id; 12 Ope(int x,int y,int z,int ty,int id):x(x),y(y),z(z),ty(ty),id(id){} 13 Ope(){} 14 }; 15 16 bool cmp_x(Ope a,Ope b){ 17 if(a.x==b.x)return a.ty<b.ty; 18 return a.x<b.x; 19 } 20 bool cmp_y(Ope a,Ope b){ 21 if(a.y==b.y)return a.ty<b.ty; 22 return a.y<b.y; 23 } 24 25 vector<Ope> ope,ope2; 26 //vector<int> allZ; 27 vector<int>::iterator it; 28 int tree[MAX_Z]; 29 int ans[MAX_Z]; 30 void add(int x,int a){ 31 while(x<MAX_Z){ 32 tree[x]+=a; 33 x+=(x&(-x)); 34 } 35 } 36 37 int read(int x){ 38 int sum=0; 39 while(x){ 40 sum+=tree[x]; 41 x-=(x&(-x)); 42 } 43 return sum; 44 } 45 46 void work(){ 47 for(int i=0;i<ope2.size();i++){ 48 if(ope2[i].ty==0) add(ope2[i].z,1); 49 else{ 50 int temp=read(ope2[i].z); 51 ans[ope2[i].id]+=temp*ope2[i].ty; 52 } 53 } 54 for(int i=0;i<ope2.size();i++) 55 if(ope2[i].ty==0) add(ope2[i].z,-1); 56 57 } 58 59 void CDQ(int L,int R){ 60 if(L>=R)return; 61 int mid=(L+R)>>1; 62 CDQ(L,mid); 63 ope2.clear(); 64 for(int i=L;i<=mid;i++){ 65 if(ope[i].ty==0) 66 ope2.push_back(ope[i]); 67 } 68 for(int i=mid+1;i<=R;i++){ 69 if(ope[i].ty!=0) 70 ope2.push_back(ope[i]); 71 } 72 sort(ope2.begin(),ope2.end(),cmp_y); 73 work(); 74 CDQ(mid+1,R); 75 } 76 77 int main(){ 78 int T; 79 int n; 80 scanf("%d",&T); 81 while(T--){ 82 scanf("%d",&n); 83 ope.clear(); 84 //allZ.clear(); 85 memset(tree,0,sizeof(tree)); 86 memset(ans,0,sizeof(ans)); 87 for(int i=1;i<=n;i++){ 88 int x,y,z; 89 scanf("%d%d%d",&x,&y,&z); 90 ope.push_back(Ope(x,y,z,0,i)); 91 ope.push_back(Ope(x,y,z,1,i)); 92 //allZ.push_back(z); 93 } 94 /* 95 sort(allZ.begin(),allZ.end()); 96 it=unique(allZ.begin(),allZ.end()); 97 allZ.resize(distance(allZ.begin(),it)); 98 for(int i=0;i<ope.size();i++){ 99 ope[i].z=lower_bound(allZ.begin(),allZ.end(),ope[i].z)-allZ.begin()+1; 100 } 101 */ 102 sort(ope.begin(),ope.end(),cmp_x); 103 CDQ(0,ope.size()-1); 104 for(int i=1;i<=n;i++){ 105 printf("%d\n",ans[i]-1); 106 } 107 } 108 return 0; 109 }
CDQ分治就是将前半截对后半截的影响拿出来,把偏序问题降维。
三维的经过一次CDQ分治变成两维,四维的可以经过两次CDQ降成两维。
两维偏序问题,一维排序,另一维做树状数组处理就可以。
这里被注释掉的,是一种离散化的姿势,mark一下。