Description
给出N个平面上的点。保证每一个点的坐标都是正奇数。
你要在平面上画两条线,一条是x=a,一条是y=b,且a和b都是偶数。
直线将平面划成4个部分,要求包含点数最多的那个部分点数最少。
Input
第一行一个数N。
接下来N行每行描述一个点
N<=100000
1<=x,y<=1000000
Output
输出一个数表示最少的点数。
枚举直线x=a的位置,将两侧的点的y坐标插入线段树中,在线段树查询在x=a确定时y=b的最优位置。
#include<cstdio> #include<algorithm> int n,ans=2147483647; inline int read(){ int x=0,c=getchar(); while(c>'9'||c<'0')c=getchar(); while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); return x; } struct pos{ int x,y; }ps[100005]; bool operator<(pos a,pos b){return a.x<b.x;} int t1[262144],t2[262144]; int tran[1000005]; void ins(int*t,int x){for(x+=131071;x;x>>=1)t[x]++;} void del(int*t,int x){for(x+=131071;x;x>>=1)t[x]--;} void cal(int x1,int x2){ int w=1,v1=t1[2],v2=t2[2],u1,u2,mx; while(1){ u1=x1-v1; u2=x2-v2; mx=v1; if(v2>mx)mx=v2; if(u1>mx)mx=u1; if(u2>mx)mx=u2; if(ans>mx)ans=mx; if(w>=65536)break; if(v1==mx||v2==mx){ w+=w; v1-=t1[(w<<1)+1]; v2-=t2[(w<<1)+1]; }else{ w+=w+1; v1+=t1[w<<1]; v2+=t2[w<<1]; } } } int main(){ n=read(); for(int i=0;i<n;i++){ ps[i].x=read(); tran[ps[i].y=read()]=1; } std::sort(ps,ps+n); for(int i=1,w=1;i<=1000000;i++)if(tran[i])tran[i]=w++; for(int i=0;i<n;i++)ps[i].y=tran[ps[i].y]; for(int i=0;i<n;i++)ins(t2,ps[i].y); cal(0,n); ps[n].x=-1; for(int i=0;i<n;i++){ del(t2,ps[i].y); ins(t1,ps[i].y); if(ps[i].x!=ps[i+1].x)cal(i+1,n-i-1); } printf("%d",ans); return 0; }