• bzoj4662: Snow


    Description

    2333年的某一天,临冬突降大雪,主干道已经被雪覆盖不能使用。城
    主 囧·雪 决定要对主干道进行一次清扫。
    临冬城的主干道可以看为一条数轴。囧·雪 一共找来了n个清理工,第
    i个清理工的工作范围为[li,ri],也就是说这个清理工会把[li,ri]这一
    段主干道清理干净(当然已经被清理过的部分就被忽略了)。当然有可能主
    干道不能全部被清理干净,不过这也没啥关系。
    虽然 囧·雪 啥都不知道,但是他还是保证了不会出现某一个清理工的
    工作范围被另一个清理工完全包含的情况(不然就太蠢了)。
    作为临冬城主,囧·雪 给出了如下的清扫方案:
    在每一天开始的时候,每一个还没有工作过的清理工会观察自己工作
    范围内的道路,并且记下工作范围内此时还没有被清理的道路的长度(称
    为这个清理工的工作长度)。然后 囧·雪 会从中选择一个工作长度最小的
    清理工(如果两个清理工工作长度相同,那么就选择编号小的清理工)。然
    后被选择的这个清理工会清理自己的工作范围内的道路。为了方便检查工
    作质量,囧·雪 希望每一天只有一个清理工在工作。
    你要注意,清理工的工作长度是可能改变的,甚至有可能变成0。尽管
    如此,这个清理工也还是会在某一天工作。
    现在,囧·雪 想要知道每一天都是哪个清理工在工作?

    Input

    第一行两个整数t,n。分别表示主干道的长度(也就是说,主干道是数
    轴上[1,t]的这一段)以及清理工的人数。
    接下来n行,每行两个整数li,ri。意义如题。
    n<=3*10^5, 1<=li<ri<=t<=10^9,保证输入的li严格递增

    Output

    输出n行,第i行表示第i天工作的清理工的编号。
    区间互不包含说明左端点升序时右端点严格单调,区间端点离散化,用线段树维护按左端点排序后工作长度的最小值,每次查出最小值后将其删去并枚举这次清扫的区间,对应在线段树中是连续的一段,可以标记实现区间减。
     
    #include<cstdio>
    #include<algorithm>
    const int N=300077;
    char buf[10000007],*ptr=buf-1;
    int _(){
        int x=0,c=*++ptr;
        while(c<48)c=*++ptr;
        while(c>47)x=x*10+c-48,c=*++ptr;
        return x;
    }
    int min(int a,int b){return a<b?a:b;}
    int mx,n,ls[N],rs[N],xs[N*2],xp=0,ans,f[N*2],_l,_r,_a;
    struct node{
        node*lc,*rc;
        int L,R,mn,a;
        void up(){mn=min(lc->mn,rc->mn);}
        void dn(){
            if(a){
                lc->mn+=a;
                lc->a+=a;
                rc->mn+=a;
                rc->a+=a;
                a=0;
            }
        }
        void dec(){
            if(_l<=L&&R<=_r){
                mn+=_a;
                a+=_a;
                return;
            }
            int M=L+R>>1;
            dn();
            if(_l<=M)lc->dec();
            if(_r>M)rc->dec();
            up();
        }
        void cal(){
            if(L==R){
                ans=L;
                mn=0x7fffffff;
                return;
            }
            dn();
            (lc->mn<=rc->mn?lc:rc)->cal();
            up();
        }
    }ns[N*2],*np=ns,*rt;
    node*build(int L,int R){
        node*w=np++;
        w->L=L;w->R=R;
        if(L==R){
            w->mn=rs[L]-ls[L];
        }else{
            int M=L+R>>1;
            w->lc=build(L,M);
            w->rc=build(M+1,R);
            w->up();
        }
        return w;
    }
    int get(int x){
        int a=x,c;
        while(x!=f[x])x=f[x];
        while(x!=f[a])c=f[a],f[a]=x,a=c;
        return x;
    }
    int main(){
        fread(buf,1,sizeof(buf),stdin);
        mx=_();n=_();
        for(int i=1;i<=n;++i){
            ls[i]=_();
            rs[i]=_();
        }
        rt=build(1,n);
        int p1=1,p2=1;
        while(p1<=n&&p2<=n){
            if(ls[p1]<rs[p2])xs[++xp]=ls[p1],ls[p1++]=xp;
            else if(ls[p1]>rs[p2])xs[++xp]=rs[p2],rs[p2++]=xp;
            else xs[++xp]=ls[p1],ls[p1++]=rs[p2++]=xp;
        }
        while(p1<=n)xs[++xp]=ls[p1],ls[p1++]=xp;
        while(p2<=n)xs[++xp]=rs[p2],rs[p2++]=xp;
        for(int i=1;i<=xp;++i)f[i]=i;
        for(int i=1;i<=n;++i){
            rt->cal();
            printf("%d
    ",ans);
            for(int p=get(ls[ans]);p<rs[ans];p=f[p]=get(p+1)){
                _l=std::upper_bound(rs+1,rs+n+1,p)-rs;
                _r=std::upper_bound(ls+1,ls+n+1,p)-ls-1;
                _a=xs[p]-xs[p+1];
                rt->dec();
            }
        }
        return 0;
    }
  • 相关阅读:
    selenium之 关闭窗口close与quit
    如何去掉xmind的备注红色下划线
    cmd里面快速粘贴复制的设置方式以及初始位置设置
    Python中的空格和缩进问题总结
    python 单例实现
    logging 简单使用
    CTypes
    类装饰器使用
    Django admin
    Django 视图
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6291464.html
Copyright © 2020-2023  润新知