ccz181078

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

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\n",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;
}

 

posted on 2017-01-16 23:52  nul  阅读(474)  评论(0编辑  收藏  举报