bzoj3898: 打的士
Posted ccz181078
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3898: 打的士相关的知识,希望对你有一定的参考价值。
Description
酒足饭饱之后。
一帮人都喝醉了。
嘛,由于酒驾查的很严格,所以说接下来就是送客人回家的难题了。
嘛,接下来就是操蛋的设定。
小T把喝醉的人分成了好多组,每一组要用一部车把他们送回家睡大觉。
然后呢,每一组可以租用的车子也是不一样的,具体而言,对于第i组,有T[i]种的车子(型号可能相同)来把他们送回去。当然咯,小T只需要安排一辆车子就可以送走这一组所有的人了。由于囊中羞射,小T一定只会每组安排一辆车。
更具体的,送回家的费用,是所有租用的车子里面,型号最大的和型号最小的车子,型号的差距。(尼玛,你这是啥题面啊,有TM啥关系啊
但是呢= =,由于喝醉的人是相继的醉,不可能啊出现如下场景:
“大家一起醉吧。”
“好!”
一杯而下,全倒了。。。
所以呢,这样动态的安排车子,又给小T加了不少麻烦。也就是说,小T需要处理如下两个操作。
1.有一组人醉倒了。
2.询问当前所有醉倒的人送回家的费用。
但是又出现了一个问题。
小A说:“你能解决,老子给你1000W。”
小T说:“你还不如把车子全租了。”
小A说:“………………”
小A思考了一下又说:“既然不能全租,那就来个限定吧,租车的型号必须大于等于L。”
小T给了小A一巴掌。。。。。。
“GFS就能拽?”
Input
第一行有一个正整数,N,表示操作的总数目。
接下来N行,每行首先包含了一个字母C或者Q。
如果是C,则表示,现在有一组人醉倒了,他们需要租车。C的后面有一个正整数T[]表示的是这一组有T[]部车子可以租。接下来有T[]个数字,分别表示他们可以租的车子的型号。
如果是Q,则后面有一个限制,L,表示对于当前所有已经醉的组,算出他们租车的最小费用。并且租车的最小型号是L。
Output
对于每一个Q操作,输出最小费用。如果无法安排,请阁下输出-1。
线段树维护一下选的最小标号为x时,最大标号的最小值以及它们的差的最小值,修改是区间对一个数取max,查询是一个后缀最大值。
#include<bits/stdc++.h> const int inf=0x7fffffff; char buf[10000000],*ptr=buf,ob[3000007],*op=ob; int _(){ int x=0; while(*ptr<48)++ptr; while(*ptr>47)x=x*10+*ptr++-48; return x; } void pr(int x){ if(x<0)*op++=‘-‘,x=-x; int ss[15],sp=0; do ss[++sp]=x%10+48;while(x/=10); while(sp)*op++=ss[sp--]; *op++=10; } int n,mem[1000007],*mp=mem; int xs[1000007],xp=0; int _l,_r,_a; void mins(int&a,int b){if(a>b)a=b;} int min(int a,int b){return a<b?a:b;} int max(int a,int b){return a>b?a:b;} struct node{ node*lc,*rc; int L,R,M; int tp,mv,mxv,ans; void fil(int x){ mv=mxv=x,tp=1; ans=x-R; } void chk(){ if(mv>=_a)return; if(mxv<_a)return fil(_a); lc->chk(); rc->chk(); up(); } void dn(){ if(tp){ lc->fil(mv); rc->fil(mv); tp=0; } } void up(){ mv=min(lc->mv,rc->mv); mxv=max(lc->mxv,rc->mxv); ans=min(lc->ans,rc->ans); } void mxs(){ if(mv>=_a)return; if(_l<=L&&R<=_r)return chk(); dn(); if(_l<=M)lc->mxs(); if(_r>M)rc->mxs(); up(); } void que(){ if(_l<=L)return mins(_a,ans); dn(); if(_l<=M)lc->que(); rc->que(); } }ns[2000007],*np=ns,*rt; node*build(int L,int R){ node*w=np++; w->L=xs[L],w->R=xs[R]; if(L<R){ int M=L+R>>1; w->M=xs[M]; w->lc=build(L,M); w->rc=build(M+1,R); w->up(); }else w->fil(xs[L]); return w; } void mxs(int l,int r){ _l=xs[l],_r=xs[r],_a=xs[r]; if(_r>=xs[xp])_r=xs[xp-1]; if(_l<=_r)rt->mxs(); } bool ed=0; struct Q{ int tp,v,*vs; void R(){ tp=_()==‘C‘-48; v=_(); if(tp){ vs=mp,mp+=v; for(int i=0;i<v;++i)xs[xp++]=vs[i]=_(); std::sort(vs,vs+v); } } void cal(){ if(tp){ ed=1; int px=0; for(int i=0;i<v;++i){ int x=std::lower_bound(xs,xs+xp,vs[i])-xs; mxs(px,x); px=x+1; } mxs(px,xp); }else{ _a=inf; _l=*std::lower_bound(xs,xs+xp,v); if(_l<xs[xp])rt->que(); if(_a>1e9)_a=-1; if(!ed)_a=0; pr(_a); } } }qs[200007]; int main(){ fread(buf,1,sizeof(buf),stdin); n=_(); for(int i=0;i<n;++i)qs[i].R(); std::sort(xs,xs+xp); xp=std::unique(xs,xs+xp)-xs; xs[xp]=inf; rt=build(0,xp-1); for(int i=0;i<n;++i)qs[i].cal(); fwrite(ob,1,op-ob,stdout); return 0; }
以上是关于bzoj3898: 打的士的主要内容,如果未能解决你的问题,请参考以下文章
bzoj4028 [HEOI2015]公约数数列(分块+卡常?)