1. 程式人生 > >noi2017 day2t2

noi2017 day2t2

nbsp view ase 時間 答案 bit item opened -h

設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