ccz181078

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

Description

幽香是幻想乡中一个非常有地位的人。她日理万机,事务繁多,反倒自己已经快管理不过来了。于是他决定开发一个日程管理软件来帮助自己管理任务。 

对于每个任务i有一个对应的截止日期ti以及收益pi,表示若幽香能在不晚于第ti天完成这个任务,便可以得到pi的收益。幽香办事的能力非常强,任何任务都可以用恰好一天的时间做完。但由于任务实在太多了,有时候并不能完成所有任务,于是幽香会想知道这个情况下,完成任务可以给她带来的最大的累积收益是多少。 
由于幻想乡的人们十分善变,任务总是不断发生着变化。幽香希望这个管理软件还能够支持插入一个任务,和删除一个任务的操作。 
具体的说,幽香希望支持以下2个操作: 
1.ADD t p:表示新添一个截止日期为t,收益为p的任务。 
2.DEL t p:表示删除一个截止日期为t,收益为p的任务。如果有多个这样的任务,只删除一个。数据保证这样的任务一定存在。 
在每次操作执行完毕后,你都需要输出能够完成的任务的最大收益和。 
幽香一共有T天需要安排,从第1天到第T天。你能帮助他写出这个高效率的软件吗? 

Input

第一行有两个证书T和Q,表示天数和操作的个数。 

接下来Q行,其中第i行表示第i个操作,形式为ADD t p或DEL t p,其具体意义如题面所述。 

Output

对每一次操作,输出一个整数在执行完该操作后幽香能够获得的最大收益和。 

考虑用最大费用流表示这个贪心(每一天拆一个点x,x到x-1连费用0流量无限的边,x到T连费用0流量1的边,任务表示为S到x的流量1费用为收益的边),对于每次ADD,相当于加入一条边,这时如果有到T的增广路就直接增广(可以做这个任务而不影响其余任务),否则若可以找到正费用的增广环(用这个任务换掉一个收益更小的任务)也可以增广,否则不操作;

对于每次DEL,如果这条边没增广,就直接删边,否则需要退掉经过这条边的流量,优先考虑找一个增广环(相当于用另一个任务换掉当前任务),找不到再考虑增广路(直接删去当前任务)。

由于图的特殊性,可以用线段树和平衡树等维护增广过程。

#include<bits/stdc++.h>
const int M=1e5,N=300007,inf=INT_MAX;
char ib[M+7],*ip=ib+M;
int G(){
    if(ip==ib+M)fread(ip=ib,1,M,stdin)[ib]=0;
    return *ip++;
}
int _(){
    int x=0,f=1;
    if(ip<ib+M-100){
        while(*ip<48)*ip++=='-'?f=-1:0;
        while(*ip>47)x=x*10+*ip++-48;
    }else{
        int c=G();
        while(c<48)c=G();
        while(c>47)x=x*10+c-48,c=G();
    }
    return x*f;
}
int min(int a,int b){return a<b?a:b;}
int max(int a,int b){return a>b?a:b;}
int _l,_r,_a;
struct node{
    node*lc,*rc;
    int L,R,M;
    int mn,a;
    void add(int x){mn+=x,a+=x;}
    void dn(){if(a)lc->add(a),rc->add(a),a=0;}
    void up(){mn=min(lc->mn,rc->mn);}
    void add(){
        if(_l<=L&&R<=_r)return add(_a);
        dn();
        if(_l<=M)lc->add();
        if(_r>M)rc->add();
        up();
    }
    bool ql(){
        if(mn)return 0;
        if(L==R)return _l=L,1;
        return dn(),_r>M&&rc->ql()||lc->ql();
    }
    bool qr(){
        if(mn)return 0;
        if(L==R)return _r=R,1;
        return dn(),_l<=M&&lc->qr()||rc->qr();
    }
}ns[N*2],*np=ns,*rt;
node*build(int L,int R){
    node*w=np++;
    w->L=L,w->R=R;
    if(L<R){
        int M=w->M=L+R>>1;
        w->lc=build(L,M);
        w->rc=build(M+1,R);
    }
    return w;
}
int gr(int x){return _l=x,rt->qr(),_r;}
int gl(int x){return _r=x-1,rt->ql(),_l+1;}
void flow(int x,int y){
    if(x<y)_l=x,_r=y-1,_a=-1,rt->add();
    if(x>y)_l=y,_r=x-1,_a=1,rt->add();
}
std::multiset<int>e0[N],e1[N];
std::multiset<int>::iterator it;
long long ans=0;
int n,qp,t1[1055555],t0[1055555],mx;
int em[1055555];
int pv_empty(int w){
    for(w+=mx+1;;w>>=1)if(w&1&&em[w-1]&1){
        for(--w;w<mx;w<<=1,w+=em[w+1]&1);
        return w-mx;
    }
}
int nx_full(int w){
    for(w+=mx-1;w;w>>=1)if(~w&1&&em[w+1]&2){
        for(++w;w<mx;w=w<<1^1,w-=em[w-1]>>1&1);
        return w-mx;
    }
    return 0;
}
void set_(int w,int v){
    for(w+=mx,em[w]=v,w>>=1;w;w>>=1)em[w]=em[w<<1]|em[w<<1^1];
}
void upd1(int w){
    t1[w+mx]=e1[w].size()?*e1[w].begin():inf;
    for(w=w+mx>>1;w;w>>=1)t1[w]=min(t1[w<<1],t1[w<<1^1]);
}
void upd0(int w){
    t0[w+mx]=e0[w].size()?*--e0[w].end():-inf;
    for(w=w+mx>>1;w;w>>=1)t0[w]=max(t0[w<<1],t0[w<<1^1]);
}
int gmn(int l,int r){
    int w=mx+l;
    for(l+=mx-1,r+=mx+1;r-l!=1;l>>=1,r>>=1){
        if(~l&1&&t1[l+1]<t1[w])w=l+1;
        if(r&1&&t1[r-1]<t1[w])w=r-1;
    }
    for(;w<mx;w=w<<1^(t1[w<<1^1]==t1[w]));
    return w-mx;
}
int gmx(int l,int r){
    int w=mx+l;
    for(l+=mx-1,r+=mx+1;r-l!=1;l>>=1,r>>=1){
        if(~l&1&&t0[l+1]>t0[w])w=l+1;
        if(r&1&&t0[r-1]>t0[w])w=r-1;
    }
    for(;w<mx;w=w<<1^(t0[w<<1^1]==t0[w]));
    return w-mx;
}
int ins(int x,int y){
    int p=gr(x),pe=pv_empty(p);
    if(pe){
        flow(x,pe);
        set_(pe,2);
        e1[x].insert(y);
        upd1(x);
        return y;
    }else{
        int z=gmn(1,p),zv=t1[mx+z];
        if(zv<y){
            flow(x,z);
            e1[x].insert(y);
            e1[z].erase(e1[z].find(zv));
            e0[z].insert(zv);
            upd1(x),upd1(z),upd0(z);
            return y-zv;
        }else{
            e0[x].insert(y);
            upd0(x);
            return 0;
        }
    }
}
int del(int x,int y){
    if((it=e0[x].find(y))!=e0[x].end()){
        e0[x].erase(it);
        upd0(x);
        return 0;
    }else{
        e1[x].erase(e1[x].find(y));
        upd1(x);
        int p=gl(x),z=gmx(p,n),zv=t0[mx+z];
        if(zv>=0){
            flow(z,x);
            e1[z].insert(zv);
            e0[z].erase(e0[z].find(zv));
            upd1(z),upd0(z);
            return zv-y;
        }
        int pf=nx_full(p);
        flow(pf,x);
        set_(pf,1);
        return -y;
    }
}
int main(){
    n=_();
    rt=build(0,n);
    for(mx=1;mx<n+5;mx<<=1);
    for(int i=0;i<mx*2;++i)t1[i]=inf,t0[i]=-inf,em[i]=1;
    for(qp=_();qp;--qp){
        int o=_(),a=_(),b=_();
        printf("%lld\n",ans+=o==1920?ins(a,b):del(a,b));
    }
    return 0;
}

 

posted on 2017-09-21 12:30  nul  阅读(523)  评论(0编辑  收藏  举报