ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

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;
}

posted on 2016-03-03 21:12  nul  阅读(612)  评论(0编辑  收藏  举报