zoukankan      html  css  js  c++  java
  • luogu P5328 [ZJOI2019]浙江省选

    传送门

    每个人都可以看成一条直线(y=ax+b),所以我们要求的是每条线在整点处,上方线的数量的最小值(注意多条直线如果交于同一整点互不影响)

    如果(m=1),其实只要求出半平面交,然后在半平面交上的线的答案就是(1).然后是(m=2),先把排名(=1)的线拿走,那么剩下的线如果排名可以为(2),那么至少应该在剩下的线的半平面交上.然后对于所有算过的线,他们都可以覆盖半平面交上的一段连续区间,可以使用二分求出覆盖的区间端点,然后就是找出在半平面交上的区域被上述区间覆盖的次数为1的线段更新答案,可以从左往右扫一遍求出,我这里用的是线段树.剩下的以此类推就好了

    注意细节较多

    // luogu-judger-enable-o2
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<map>
    #include<set>
    #define LL long long
    #define db long double
    
    using namespace std;
    const int N=1e5+10;
    const db eps=1e-10;
    LL rd()
    {
        LL x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    struct point
    {
        db x,y;
        point(){}
        point(db nx,db ny){x=nx,y=ny;}
        point operator - (const point &bb) const {return point(x-bb.x,y-bb.y);}
        db operator ^ (const point &bb) const {return x*bb.y-y*bb.x;}
    };
    struct line
    {
        db k,b;
        int i;
        bool operator < (const line &bb) const {return fabs(k-bb.k)>eps?k<bb.k:b<bb.b;}
    }a[N],p[N],st[N];
    point jiao(line a,line b){db xx=(a.b-b.b)/(b.k-a.k),yy=a.k*xx+a.b;return point(xx,yy);}
    db nx[N];
    int n,m,an[N],tl,tp;
    LL li[N][2],q[N][2],cg[N][2],bb[N<<2],mm;
    int mi[N<<4],tg[N<<4],va[N];
    void psup(int o){mi[o]=min(mi[o<<1],mi[o<<1|1]);}
    void ad(int o,int x){mi[o]+=x,tg[o]+=x;}
    void psdn(int o){if(tg[o]) ad(o<<1,tg[o]),ad(o<<1|1,tg[o]),tg[o]=0;}
    void modif(int o,int l,int r,int ll,int rr)
    {
        if(ll<=l&&r<=rr){ad(o,1);return;}
        psdn(o);
        int mid=(l+r)>>1;
        if(ll<=mid) modif(o<<1,l,mid,ll,rr);
        if(rr>mid) modif(o<<1|1,mid+1,r,ll,rr);
        psup(o);
    }
    int quer(int o,int l,int r,int ll,int rr)
    {
        if(ll<=l&&r<=rr) return mi[o];
        psdn(o);
        int an=1<<29,mid=(l+r)>>1;
        if(ll<=mid) an=min(an,quer(o<<1,l,mid,ll,rr));
        if(rr>mid) an=min(an,quer(o<<1|1,mid+1,r,ll,rr));
        psup(o);
        return an;
    }
    
    int main()
    {
        nx[0]=-1e18;
        n=rd(),m=rd();
        for(int i=1;i<=n;++i)
        {
            an[i]=-1;
            li[i][0]=rd(),li[i][1]=rd();
        }
        int nn;
        for(int h=1;h<=m;++h)
        {
            sort(p+1,p+tl+1);
            nn=0;
            for(int i=1;i<=n;++i)
                if(an[i]==-1) a[++nn]=(line){li[i][0],li[i][1],i};
            if(!nn) break;
            sort(a+1,a+nn+1);
            a[nn+1].k=-1;
            tp=0;
            for(int i=1;i<=nn;++i)
            {
                if(a[i].k==a[i+1].k) continue;
                while(tp>1&&jiao(a[i],st[tp]).y-jiao(a[i],st[tp-1]).y<-eps) --tp;
                st[++tp]=a[i];
            }
            mm=0;
            db xx=0;
            for(int i=1;i<=tp;++i)
            {
                nx[i]=i<tp?jiao(st[i],st[i+1]).x:1e18;
                q[i][0]=max((LL)(fabs(xx-floor(xx+0.5))<eps?(xx+0.5):ceil(xx)),0ll);
                q[i][1]=max((LL)(fabs(nx[i]-floor(nx[i]+0.5))<eps?(nx[i]+0.5):floor(nx[i])),-1ll);
                xx=nx[i];
                bb[++mm]=q[i][0],bb[++mm]=q[i][1];
            }
            for(int i=1;i<=tl;++i)
            {
                //if(i==67) {int Q=5e8;while(Q--);}
                int l=1,r=tp,z=tp;
                while(l<=r)
                {
                    int mid=(l+r)>>1;
                    if(p[i].k<=st[mid].k) z=mid,r=mid-1;
                    else l=mid+1;
                }
                int zz=0;
                l=1,r=z-(p[i].k<=st[z].k);
                while(l<=r)
                {
                    int mid=(l+r)>>1;
                    xx=jiao(p[i],st[mid]).x;
                    if(xx>nx[mid-1]-eps) zz=mid,l=mid+1;
                    else r=mid-1;
                }
                if(zz)
                {
                    xx=jiao(p[i],st[zz]).x;
                    //if((LL)(xx+0.5)==3149034259) {int Q=5e8;while(Q--);}
                    cg[i][0]=(LL)floor(xx)+1;
                }
                else cg[i][0]=0;
                zz=0;
                l=z+(p[i].k>=st[z].k),r=tp;
                while(l<=r)
                {
                    int mid=(l+r)>>1;
                    xx=jiao(p[i],st[mid]).x;
                    if(xx<nx[mid]+eps) zz=mid,r=mid-1;
                    else l=mid+1;
                }
                if(zz)
                {
                    xx=jiao(p[i],st[zz]).x;
                    cg[i][1]=(LL)ceil(xx)-1;
                }
                else cg[i][1]=1e18;
                bb[++mm]=cg[i][0],bb[++mm]=cg[i][1];
                //printf("%lld %lld
    ",cg[i][0],cg[i][1]);
            }
            sort(bb+1,bb+mm+1),mm=unique(bb+1,bb+mm+1)-bb-1;
            nn=mm;
            for(int i=2;i<=nn;++i)
                if(bb[i]-bb[i-1]>1) bb[++mm]=(bb[i]+bb[i-1])>>1;
            sort(bb+1,bb+mm+1),mm=unique(bb+1,bb+mm+1)-bb-1;
            for(int i=0;i<=(mm<<2);++i) mi[i]=tg[i]=0;
            for(int i=1;i<=tl;++i)
            {
                cg[i][0]=lower_bound(bb+1,bb+mm+1,cg[i][0])-bb;
                cg[i][1]=lower_bound(bb+1,bb+mm+1,cg[i][1])-bb;
                modif(1,1,mm,cg[i][0],cg[i][1]);
            }
            int mx=1<<29;
            for(int i=1;i<=tp;++i)
            {
                //if(h==2&&st[i].i==75849){int Q=5e8;while(Q--);}
                q[i][0]=lower_bound(bb+1,bb+mm+1,q[i][0])-bb;
                q[i][1]=lower_bound(bb+1,bb+mm+1,q[i][1])-bb;
                va[i]=q[i][0]<=q[i][1]?quer(1,1,mm,q[i][0],q[i][1]):1<<29;
                mx=min(mx,va[i]);
                //if(va[i]<n)printf("%d
    ",st[i].i);
            }
            h=mx+1;
            if(h>m) break;
            for(int i=1;i<=tp;++i)
                if(va[i]+1==h) an[st[i].i]=h,p[++tl]=st[i]/*,printf("%d %d
    ",st[i].i,h)*/;
            //puts("---");
        }
        for(int i=1;i<=n;++i) printf("%d ",an[i]);
        return 0;
    }
    
  • 相关阅读:
    Anaconda的安装和更新
    Python数据分析学习目录
    国标28181sip开源库介绍(陆续补充完备)
    开源sip server & sip client 和开发库 一览
    几种开源SIP协议栈对比
    用TCP穿透NAT(TCP打洞)的实现
    使用TCP协议的NAT穿透技术
    TCP点对点穿透探索--失败
    snmp++开发实例一
    socket跟TCP/IP 的关系,单台服务器上的并发TCP连接数可以有多少
  • 原文地址:https://www.cnblogs.com/smyjr/p/10901945.html
Copyright © 2011-2022 走看看