poj2464

  1 /*
  2 题意:给你n个点,先选一条过至少一个点的垂线,然后在垂线上选一个点,过该点做水平线,
  3 将图分成四部分,记为ul,ur,dl,dr,问选一条直线使得对于最坏情况选的水平线下,使得dl+ur最大的值;
  4 同时输出在dl+ur最大的情况下ul+dr的可能值;
  5 
  6 思路:先离散,因为题目没有说明数据范围,
  7 然后依次枚举每一条垂直线,再从下到上枚举每一个点,利用树状数组记录;
  8 最后输出解;
  9 
 10 */
 11 
 12 #include<cstdio>
 13 #include<cstring>
 14 #include<cstdlib>
 15 #include<set>
 16 #include<algorithm>
 17 #include<cmath>
 18 #include<iostream>
 19 #include<vector>
 20 using namespace std;
 21 const int N=200000+10;
 22 int n;
 23 int n1,n2;
 24 int c1[N],c2[N];
 25 vector<int> X,Y,g[N];
 26 inline int lowbit(int x){
 27     return x&-x;
 28 }
 29 inline void add(int c[],int x,int v){
 30     for (int i=x;i<N;i+=lowbit(i)){
 31         c[i]+=v;
 32     }
 33 }
 34 inline int sum(int c[],int x){
 35     int ret=0;
 36     for (int i=x;i>0;i-=lowbit(i)){
 37         ret+=c[i];
 38     }
 39     return ret;
 40 }
 41 int x[N],y[N];
 42 void read(){
 43     memset(c1,0,sizeof(c1));
 44     memset(c2,0,sizeof(c2));
 45     X.clear();Y.clear();
 46 
 47     for (int i=0;i<n;i++){
 48        scanf("%d%d",x+i,y+i);
 49        X.push_back(x[i]);
 50        Y.push_back(y[i]);
 51     }
 52     sort(X.begin(),X.end());
 53     n1=unique(X.begin(),X.end())-X.begin();
 54     sort(Y.begin(),Y.end());
 55     n2=unique(Y.begin(),Y.end())-Y.begin();
 56 
 57     for (int i=0;i<=n;i++) g[i].clear();
 58     for (int i=0;i<n;i++){
 59         int tmp=(lower_bound(X.begin(),X.begin()+n1,x[i])-X.begin())+1;
 60         int tmp2=(lower_bound(Y.begin(),Y.begin()+n2,y[i])-Y.begin())+1;
 61         g[tmp].push_back(tmp2);
 62         add(c1,tmp2,1);
 63     }
 64 }
 65 void work(){
 66     int ret=-1;
 67     vector<int> ans;
 68     ans.clear();
 69     for (int i=0;i<=n;i++){
 70         int sz=g[i].size();
 71         if (sz!=0){
 72             vector<int> ans1;
 73             ans1.clear();
 74             int rt1=-1,a1,a2,a3,a4;//四个象限ul,ur,dl,dr;
 75             sort(g[i].begin(),g[i].end());
 76             for (int j=0;j<sz;j++){
 77                 int t1=sum(c1,g[i][j]-1);
 78                 a3=sum(c2,g[i][j]-1);
 79                 a4=t1-a3-j;
 80                 int t2=sum(c1,N-1)-sum(c1,g[i][j]);
 81                 a1=sum(c2,N-1)-sum(c2,g[i][j]);
 82                 a2=t2-a1-(sz-j-1);
 83                 if (a2+a3<rt1 || rt1==-1) {
 84                     rt1=a2+a3;
 85                     ans1.clear();
 86                     ans1.push_back(a1+a4);
 87                 }else if(a2+a3==rt1){
 88                     ans1.push_back(a1+a4);
 89                 }
 90             }
 91             for (int j=0;j<sz;j++){
 92                 add(c2,g[i][j],1);
 93             }
 94             if (rt1>ret || ret==-1){
 95                 ret=rt1;
 96                 ans.clear();
 97                 for (int j=0;j<ans1.size();j++){
 98                     ans.push_back(ans1[j]);
 99                 }
100             }else if (rt1==ret){
101                 for(int j=0;j<ans1.size();j++){
102                     ans.push_back(ans1[j]);
103                 }
104             }
105         }
106     }
107     sort(ans.begin(),ans.end());
108     int n2=unique(ans.begin(),ans.end())-ans.begin();
109     printf("Stan: %d; Ollie:",ret);
110     for (int i=0;i<n2;i++){
111         printf(" %d",ans[i]);
112     }printf(";\n");
113 }
114 int main(){
115     while (~scanf("%d",&n),n){
116         read();
117         work();
118     }
119     return 0;
120 }
原文地址:https://www.cnblogs.com/Rlemon/p/3080844.html