考场上怕是石乐志。
状态设计还是很自然的,求什么设什么。
f[i]表示前i个人安排好,电梯最早回到0层的时间
转移的话,枚举上一次最后一个带走的是谁
f[i]=min(max(f[j],t[i])+2*max(ak,j<k<=i))
线段树优化
后面的区间最大值,可以用单调栈记录,弹栈的时候,在线段树上区间赋值
t,f都是单调不降的,所以可以边找答案边二分,一半用t[i]和ak更新。一半用f[j]和ak更新。
记录区间最小ak,最小f[j]+aj,最小f[j],最大f[j](便于二分)
#include<bits/stdc++.h> #define reg register int #define il inline #define mid ((l+r)>>1) #define numb (ch^'0') #define ls (x<<1) #define rs (x<<1|1) using namespace std; typedef long long ll; il void rd(int &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } namespace Miracle{ const int N=100000+5; int n; struct node{ ll mi,fmi,vmi,fmx; ll ch; node(){ ch=-1; } }t[8*N]; int tim[N],a[N]; int b[N]; int sta[2*N],top; ll f[N]; void pushup(int x){ t[x].mi=min(t[x<<1].mi,t[x<<1|1].mi); t[x].fmi=min(t[x<<1].fmi,t[x<<1|1].fmi); t[x].vmi=min(t[x<<1].vmi,t[x<<1|1].vmi); t[x].fmx=max(t[ls].fmx,t[rs].fmx); } void pushdown(int x){ if(t[x].ch==-1) return; t[ls].ch=t[x].ch; t[ls].vmi=t[x].ch; t[ls].mi=t[ls].fmi+2*t[ls].vmi; t[rs].ch=t[x].ch; t[rs].vmi=t[x].ch; t[rs].mi=t[rs].fmi+2*t[rs].vmi; t[x].ch=-1; } void upda(int x,int l,int r,int to,ll ak,ll c){ if(l==r){ t[x].fmi=c; t[x].fmx=c; t[x].vmi=ak; t[x].mi=t[x].fmi+2*t[x].vmi; return; } pushdown(x); if(to<=mid) upda(x<<1,l,mid,to,ak,c); else upda(x<<1|1,mid+1,r,to,ak,c); pushup(x); } void chan(int x,int l,int r,int L,int R,ll c){ if(L<=l&&r<=R){ t[x].ch=c; t[x].vmi=t[x].ch; t[x].mi=t[x].fmi+2*t[x].vmi; return; } pushdown(x); if(L<=mid) chan(x<<1,l,mid,L,R,c); if(mid<R) chan(x<<1|1,mid+1,r,L,R,c); pushup(x); } ll query(int x,int l,int r,int L,int R,ll c){ if(L<=l&&r<=R){ pushdown(x); if(t[x].fmi<t[x].fmx&&t[x].fmi<=c&&c<=t[x].fmx){ return min(query(x<<1,l,mid,L,R,c),query(x<<1|1,mid+1,r,L,R,c)); } if(t[x].fmx<=c){ return c+2*t[x].vmi; } if(t[x].fmi>=c){ return t[x].mi; } } pushdown(x); ll ret=0x3f3f3f3f3f3f3f3f; if(L<=mid) ret=min(ret,query(x<<1,l,mid,L,R,c)); if(mid<R) ret=min(ret,query(x<<1|1,mid+1,r,L,R,c)); return ret; } int main(){ rd(n); for(reg i=2;i<=n+1;++i){ rd(tim[i]),rd(a[i]); } for(reg i=1;i<=n;++i){ b[i]=a[i+1]; } sta[++top]=1; upda(1,1,n,1,b[1],0); for(reg i=2;i<=n+1;++i){ //cout<<" ii "<<i<<endl; f[i]=query(1,1,n,1,i-1,tim[i]); //cout<<" f[i] "<<f[i]<<endl; if(i!=n+1) { upda(1,1,n,i,b[i],f[i]); while(top&&b[sta[top]]<b[i]){ //cout<<sta[top]<<endl; chan(1,1,n,sta[top-1]+1,sta[top],b[i]); --top; } sta[++top]=i; } } printf("%lld",f[n+1]); return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2018/12/24 21:59:28 */