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 }