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

posted @ 2016-09-05 20:27  徐王  阅读(1137)  评论(1编辑  收藏  举报