zoukankan      html  css  js  c++  java
  • BZOJ4411

    Portal

    Description

    给出平面上的(n(nleq10^5))个整点。画两条直线(x=x_0)(y=y_0)将这些点划分成(s_1,s_2,s_3,s_4)个点,最小化(max{s_1,s_2,s_3,s_4})

    Solution

    二分答案+线段树。
    首先进行离散化,记录(sumY[i])表示(yleq i)的点的个数。
    检查(m)是否合法时,枚举(x_0)并查找是否存在合法的(y_0)。将↖称为(s_1),↙称为(s_2),↗称为(s_3),↘称为(s_4)。那么我们找到使得(s_1,s_2leq m)的最大的(y_0),然后检查(s_3,s_4)是否不超过(m)。我们将(xleq x_0)的点加入线段树,在线段树上二分来找到最大的(y_0)使得线段树上([1,y_0])中的点数和(即(s_1))不超过(m)(s_2=sumY[y_0]-s_1)也不超过(m)。找到(y_0)后检查(s_3=sum[rt]-s_1,s_4=n-s_1-s_2-s_3)是否均不超过(m),若均合法则说明(ansleq m),否则继续枚举(x_0)。若对于所有(x_0)均不存在合法的(y_0),则说明(ans>m)

    时间复杂度(O(nlog^2n))

    Code

    //[Usaco2016 Feb]Load balancing
    #include <algorithm>
    #include <cstdio>
    using namespace std;
    inline char gc()
    {
        static char now[1<<16],*s,*t;
        if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
        return *s++;
    }
    inline int read()
    {
        int x=0; char ch=gc();
        while(ch<'0'||'9'<ch) ch=gc();
        while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
        return x;
    }
    const int N=1e5+10;
    int n,nX,nY; int sumY[N];
    struct point{int x,y;} pt[N];
    bool cmpX(point x,point y) {return x.x<y.x;}
    int mapX[N],mapY[N];
    void discrete()
    {
        for(int i=1;i<=n;i++) mapX[i]=pt[i].x,mapY[i]=pt[i].y;
        sort(mapX+1,mapX+n+1); nX=unique(mapX+1,mapX+n+1)-mapX-1;
        for(int i=1;i<=n;i++) pt[i].x=lower_bound(mapX+1,mapX+nX+1,pt[i].x)-mapX;
        sort(mapY+1,mapY+n+1); nY=unique(mapY+1,mapY+n+1)-mapY-1;
        for(int i=1;i<=n;i++) pt[i].y=lower_bound(mapY+1,mapY+nY+1,pt[i].y)-mapY;
        sort(pt+1,pt+n+1,cmpX);
    }
    const int Ns=4e5+10;
    #define Ls (p<<1)
    #define Rs (p<<1|1)
    int rt,sum[Ns]; int clr[Ns];
    int optL,optR;
    void update(int p) {sum[p]=sum[Ls]+sum[Rs];}
    void pushdw(int p) {if(clr[p]) sum[Ls]=sum[Rs]=0,clr[Ls]=clr[Rs]=true,clr[p]=false;}
    void ins(int p,int L0,int R0,int x,int v)
    {
        if(L0==R0) {sum[p]+=v; return;}
        pushdw(p);
        int mid=L0+R0>>1;
        if(x<=mid) ins(Ls,L0,mid,x,v);
        else ins(Rs,mid+1,R0,x,v);
        update(p);
    }
    int query1(int p,int L0,int R0,int s1,int x)
    {
        if(L0==R0) return L0;
        pushdw(p);
        int mid=L0+R0>>1; int t1=s1+sum[Ls],t2=sumY[mid]-t1;
        if(x<t1||x<t2) return query1(Ls,L0,mid,s1,x);
        else return query1(Rs,mid+1,R0,t1,x);
    }
    int query2(int p,int L0,int R0)
    {
        if(optL<=L0&&R0<=optR) return sum[p];
        pushdw(p);
        int mid=L0+R0>>1; int res=0;
        if(optL<=mid) res+=query2(Ls,L0,mid);
        if(mid<optR) res+=query2(Rs,mid+1,R0);
        return res;
    }
    bool check(int m)
    {
        rt=1; sum[rt]=0,clr[rt]=true;
        for(int i=1,t=1;i<=nX;i++)
        {
            while(pt[t].x==i) ins(rt,1,nY,pt[t].y,1),t++;
            if(sum[rt]>m+m) break;
            else if(n-sum[rt]>m+m) continue;
            int j=query1(rt,1,nY,0,m)-1;
            optL=1,optR=j; int s1=query2(rt,1,nY);
            int s2=sumY[j]-s1,s3=sum[rt]-s1,s4=n-s1-s2-s3;
            if(s1>m||s2>m) printf("query1 GG
    ");
            if(s3<=m&&s4<=m) return true; 
        }
        return false;
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) pt[i].x=read(),pt[i].y=read();
        discrete();
        for(int i=1;i<=n;i++) sumY[pt[i].y]++;
        for(int i=1;i<=nY;i++) sumY[i]+=sumY[i-1];
        int L=n/4-1,R=n;
        while(L<=R)
        {
            int mid=L+R>>1;
            if(check(mid)) R=mid-1;
            else L=mid+1;
        }
        printf("%d
    ",L);
        return 0;
    }
    

    P.S.

    sro Icefox的(O(nlogn))做法 orz,比我强多啦

  • 相关阅读:
    特征选择常用算法综述
    干货:结合Scikit-learn介绍几种常用的特征选择方法
    机器学习中,有哪些特征选择的工程方法?
    牛逼的博客地址
    Discover Feature Engineering, How to Engineer Features and How to Get Good at It
    机器学习中的Bias(偏差),Error(误差),和Variance(方差)有什么区别和联系?
    机器学习中使用「正则化来防止过拟合」到底是一个什么原理?为什么正则化项就可以防止过拟合?
    Libsvm和Liblinear的使用经验谈
    Python 由list转为dictionary
    使用 numpy.random.choice随机采样
  • 原文地址:https://www.cnblogs.com/VisJiao/p/BZOJ4411.html
Copyright © 2011-2022 走看看