题意:在平面直角坐标系中给你N个点,stan和ollie玩一个游戏,首先stan在竖直方向上画一条直线,该直线必须要过其中的某个点,然后ollie在水平方向上画一条直线,该直线的要求是要经过一个stan之前画过的点。这时候平面就被分割成了四块,两个人这时候会有一个得分,stan的得分是平面上第1、3象限内的点的个数,ollie的得分是平面上第2、4象限内的点的个数,在统计的时候在所画线上的点都不计算在内。求最终stan使得自己的最差得分最高,并且输出此时ollie的得分。
(N<=2e5)
思路:
我们可以枚举分界线,分界线左右两边各维护一个线段树
枚举分界线上的每个点的y值,那么1,3象限对应的y值也就能确定了
那么就可以确定在1,3象限的点的个数,对应的2,4象限用vector存起来
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
#define INF 0x3f3f3f3f
const int N=2e5+10;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct Point{
int x,y;
}a[N];
int t[N];
int sumv[2][N*4],Count[N],x[N];
vector<int>tmp;
bool cmp(Point u,Point v){
if(u.x!=v.x)
return u.x<v.x;
return u.y<v.y;
}
int pos,d;
void pushup(int rt,int flag){
sumv[flag][rt]=sumv[flag][rt<<1]+sumv[flag][rt<<1|1];
}
void update(int l,int r,int rt,int flag){
if(l==r){
sumv[flag][rt]+=d;
return ;
}
int m=(l+r)>>1;
if(pos<=m) update(lson,flag);
else update(rson,flag);
pushup(rt,flag);
}
int L,R;
int query(int l,int r,int rt,int flag){
if(L<=l&&R>=r)
return sumv[flag][rt];
int m=l+r>>1,Ans=0;
if(L<=m) Ans+=query(lson,flag);
if(R>m) Ans+=query(rson,flag);
return Ans;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
if(n==0) break;
tmp.clear();
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].x,&a[i].y);
t[i]=a[i].y,x[i]=a[i].x;
}
sort(a+1,a+n+1,cmp);
sort(t+1,t+n+1);
sort(x+1,x+n+1);
int m=unique(t+1,t+n+1)-t-1,mm=unique(x+1,x+n+1)-x-1;
memset(sumv,0,sizeof(sumv));
memset(Count,0,sizeof(Count)); //每一行有多少个
for(int i=1;i<=n;i++){ //将点全部插入到第二颗
pos=lower_bound(t+1,t+m+1,a[i].y)-t,d=1;
Count[pos]++;
update(1,n,1,1);
}
int st=1,Stan=0;
for(int i=1;i<=mm;i++){
int ed=st;
while(st<=n&&a[st].x==x[i]){ //同一列一起处理
pos=lower_bound(t+1,t+m+1,a[st].y)-t,d=-1;
update(1,n,1,1);
++st;
}
int Ollie=-1,stan=-1;
for(int j=ed;j<st;j++){ //枚举取哪一个点
int num=lower_bound(t+1,t+m+1,a[j].y)-t,Ans=0;
while(j-1>=ed&&a[j].y==a[j-1].y){
}
L=num+1,R=m;
if(L<=R) Ans+=query(1,n,1,1);
L=1,R=num-1;
if(L<=R) Ans+=query(1,n,1,0);
if(n-(st-ed)-Count[num]+1-Ans>Ollie)
stan=Ans,Ollie=n-(st-ed)-Count[num]+1-Ans;
else if(n-(st-ed)-Count[num]+1-Ans==Ollie)
stan=min(stan,Ans);
}
if(stan>Stan){
tmp.clear();
Stan=stan;
}
if(stan==Stan)
tmp.push_back(Ollie);
for(int j=ed;j<st;j++){
int num=lower_bound(t+1,t+m+1,a[j].y)-t;
pos=num,d=1;
update(1,n,1,0);
}
}
sort(tmp.begin(),tmp.end());
vector<int>::iterator iter=unique(tmp.begin(),tmp.end());
tmp.erase(iter,tmp.end());
printf("Stan: %d; Ollie:",Stan);
for(int i=0;i<tmp.size();i++) printf(" %d",tmp[i]);
printf(";\n");
}
return 0;
}