题目链接:http://poj.org/problem?id=2464
题意:平面上有n个点。Stan选一个点A画一条垂线经过A(x值与A相同的点也会被穿过),Ollie在这条垂线所穿过的点中选一个点B用一条水平线穿过它,这样把平面分到四个区域,Stan的得分为右上和左下的点的个数,Ollie为右下和左上的点的个数。Stan先画。Stan选点的策略是使得在Ollie画完后(Ollie可能有好多选择),他的得分的最低值最大;Ollie选点的策略是使得他的得分最大。求Stan的得分和Ollie的得分,Ollie可能有多种得分,升序输出。
思路:预处理出每个点上下左右与该点在一条线上的点的个数以及在该点上方的点的个数。按照x升序y升序排序,依次插入统计。。
#include <iostream>
#include <cstdio>
#include <algorithm>
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;
struct node
{
int x,y,id;
};
const int MAX=200005;
node p[MAX];
int L[MAX],R[MAX],U[MAX],D[MAX];
int id[MAX],Y[MAX],n;
int set[MAX];
void InPut()
{
int i;
for(i=0;i<n;i++)
{
scanf("%d%d",&p[i].x,&p[i].y);
p[i].id=i;
}
for(i=0;i<n;i++) L[i]=R[i]=U[i]=D[i]=Y[i]=0;
}
int cmp1(node a,node b)
{
if(a.y!=b.y) return a.y<b.y;
return a.x<b.x;
}
int cmp2(node a,node b)
{
if(a.x!=b.x) return a.x<b.x;
return a.y<b.y;
}
void init()
{
sort(p,p+n,cmp1);
int i;
for(i=1;i<n;i++) if(p[i].y==p[i-1].y) L[p[i].id]=L[p[i-1].id]+1;
for(i=n-2;i>=0;i--) if(p[i].y==p[i+1].y) R[p[i].id]=R[p[i+1].id]+1;
for(i=n-2;i>=0;i--)
{
if(p[i].y==p[i+1].y) Y[p[i].id]=Y[p[i+1].id];
else Y[p[i].id]=n-i-1;
}
int cnt=1;
id[p[0].id]=cnt;
for(i=1;i<n;i++)
{
if(p[i].y==p[i-1].y) id[p[i].id]=cnt;
else id[p[i].id]=++cnt;
}
sort(p,p+n,cmp2);
for(i=1;i<n;i++) if(p[i].x==p[i-1].x) D[p[i].id]=D[p[i-1].id]+1;
for(i=n-2;i>=0;i--) if(p[i].x==p[i+1].x) U[p[i].id]=U[p[i+1].id]+1;
}
int lowbit(int x)
{
return x&(-x);
}
void add(int x)
{
while(x<MAX) set[x]++,x+=lowbit(x);
}
int getsum(int x)
{
int sum=0;
while(x) sum+=set[x],x-=lowbit(x);
return sum;
}
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
int ans[MAX],ansNum,Max;
void print()
{
sort(ans+1,ans+ansNum+1);
printf("Stan: %d; Ollie:",Max);
int i;
for(i=1;i<=ansNum;i++) if(i==1||ans[i]!=ans[i-1]) printf(" %d",ans[i]);
puts(";");
}
int main()
{
while(scanf("%d",&n),n)
{
InPut();
init();
memset(set,0,sizeof(set));
int pre=p[0].x,i;
int tempS,tempO,BL,TL,TR,BR,xid,temp;
int sum;
ansNum=Max=0;
for(i=0;i<n;i++)
{
xid=p[i].id;
tempS=-1,tempO=-1;
while(i<n&&p[i].x==pre)
{
sum=getsum(id[xid]);
add(id[xid]);
BL=sum-L[xid]-D[xid];
TL=i-sum;
TR=Y[xid]-TL-U[xid];
BR=n-1-BL-TL-TR-R[xid]-L[xid]-U[xid]-D[xid];
temp=TL+BR;
if(temp>tempO) tempO=temp,tempS=TR+BL;
else if(temp==tempO) tempS=min(tempS,TR+BL);
xid=p[++i].id;
}
if(i<n) pre=p[i--].x;
if(tempS>Max) Max=tempS,ansNum=1,ans[1]=tempO;
else if(tempS==Max) ans[++ansNum]=tempO;
}
print();
}
return 0;
}