首页 > 其他 > 详细

noi2017 day2t2

时间:2017-08-19 10:41:19      阅读:356      评论:0      收藏:0      [点我收藏+]

设a[i]为当前方案中第 1..i 天变质的蔬菜有几个,b[i]为前i天至少能卖出几个,方案可行的条件是对任意i有a[i]<=b[i],用线段树维护b[i]-a[i]。

从小到大枚举天数,枚举到第w天时,对所有u>=w,b[u]+=m,表示第w天从可以卖0个变为m个

选一个蔬菜,在第w天变质,则相当于对所有u>=w,a[u]+=1,因此必须保证w在b[i]-a[i]的最右一个零点的右侧

对每种蔬菜都贪心先取变质时间晚的,用另一颗线段树维护变质时间>=w的最大价值,每次贪心选可行的价值最大的一个更新答案

可以构造一个等价的费用流模型,从而证明贪心的正确性

技术分享
#include<bits/stdc++.h>
const int N=1e5+777;
typedef long long i64;
char ib[N*100],*ip=ib,ob[N*25],*op=ob;
int _(){
    int x=0;
    while(*ip<48)++ip;
    while(*ip>47)x=x*10+*ip++-48;
    return x;
}
void pr(i64 x){
    int ss[25],sp=0;
    do ss[++sp]=x%10+48;while(x/=10);
    while(sp)*op++=ss[sp--];
    *op++=10;
}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int n,m,qp;
i64 as[N],ans=0;
int qs[N],md=1;
struct item{
    int a,s,c,x;
    void R(){
        a=_(),s=_(),c=_(),x=_();
        a+=s;
    }
    void ins();
    void dec(){
        ans+=a;
        --c;
        if(s)a-=s,s=0;
    }
    int tm(){
        if(!x)return md;
        return min(md,(c+x-1)/x);
    }
    bool operator<(const item&i)const{return a>i.a;}
}is[N];
std::multiset<item>st[N];
int tr[1<<18|111],mx=0;
void up(int x){
    tr[mx+x]=st[x].size()?st[x].begin()->a:0;
    for(x=mx+x>>1;x;x>>=1)tr[x]=max(tr[x<<1],tr[x<<1^1]);
}
void item::ins(){
    if(c<=0)return;
    int x=tm();
    st[x].insert(*this);
    up(x);
}
void maxs(int&a,int b){if(a<b)a=b;}
void mins(int&a,int b){if(a>b)a=b;}
int _l,_a;
struct node{
    node*lc,*rc;
    int L,R,M;
    int v,a,p;
    void add(int x){
        v+=x,a+=x;
    }
    void add(){
        if(_l<=L)return add(_a);
        dn();
        if(_l<=M)lc->add();
        rc->add();
        up();
    }
    void dn(){
        if(a){
            lc->add(a);
            rc->add(a);
            a=0;
        }
    }
    void up(){
        v=rc->v,p=rc->p;
        if(lc->v<v)v=lc->v,p=lc->p;
    }
}ns[N*2],*np=ns,*rt;
node*build(int L,int R){
    node*w=np++;
    w->L=L,w->R=R;
    w->p=R;
    if(L<R){
        int M=w->M=L+R>>1;
        w->lc=build(L,M);
        w->rc=build(M+1,R);
    }
    return w;
}
bool chk(int pos){
    int mw=0;
    for(int w=mx+pos-1;w;w>>=1)if((~w&1)&&tr[w+1]>tr[mw])mw=w+1;
    if(!mw)return 0;
    for(;mw<mx;mw<<=1,mw+=(tr[mw]<tr[mw+1]));
    mw-=mx;
    item i=*st[mw].begin();
    st[mw].erase(st[mw].begin());up(mw);
    i.dec();
    i.ins();
    _l=mw,_a=-1,rt->add();
    return 1;
}
int main(){
    fread(ib,1,sizeof(ib),stdin);
    n=_();m=_();qp=_();
    for(int i=0;i<n;++i)is[i].R();
    for(int i=0;i<qp;++i)maxs(md,qs[i]=_());
    rt=build(1,md);
    for(mx=1;mx<=md+10;mx<<=1);
    for(int i=0;i<n;++i)is[i].ins();
    for(int i=1;i<=md;++i){
        _l=i,_a=m,rt->add();
        while(1){
            int pos=rt->v?1:rt->p+1;
            if(pos>n||!chk(pos))break;
        }
        as[i]=ans;
    }
    for(int i=0;i<qp;++i)pr(as[qs[i]]);
    fwrite(ob,1,op-ob,stdout);
    return 0;
}
View Code

 

noi2017 day2t2

原文:http://www.cnblogs.com/ccz181078/p/7392451.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!