首页 > 代码库 > NEUOJ 1702 撩妹全靠魅力值 (三维偏序)

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一下。

NEUOJ 1702 撩妹全靠魅力值 (三维偏序)