【题解】P7057 [NWRRC2015]Journey to the “The World’s Start”
upd 2023.12.28:修改了一处代码错误。
线段树优化 dp。
题目大意
你要从第
在第
例如样例就是选择了
题目分析
如果要从
有个很明显的单调性,就是如果
所以只用找出来最小满足条件的
这个东西可以用二分找,现在的关键便是如何求第
假设目前用的是第
首先我只能坐地铁到后面的点,不然肯定不优。
然后开始想各种各样的贪心,发现都是错的(有兴趣的可以试一下能不能做)。于是开始想如何 dp。
设
根据前面的条件,
如果我们暴力求解,这样时间是
观察式子,极其简单,只有一个区间求
时间复杂度
代码
#include<bits/stdc++.h>
#define ll long long
#define LC x<<1
#define RC x<<1|1
using namespace std;
ll n,t,p[50050],d[50050],f[50050],tree[200020],ans=8e18;
void pushup(ll x){
tree[x]=min(tree[LC],tree[RC]);
}
void mdf(ll x,ll l,ll r,ll pos,ll v){
if(l==r){
tree[x]=v;
return;
}
ll mid=(l+r)>>1;
if(pos<=mid) mdf(LC,l,mid,pos,v);
else mdf(RC,mid+1,r,pos,v);
pushup(x);
}
ll query(ll x,ll l,ll r,ll ql,ll qr){
if(ql<=l&&r<=qr) return tree[x];
ll mid=(l+r)>>1,res=8e18;
if(ql<=mid) res=min(res,query(LC,l,mid,ql,qr));
if(mid<qr) res=min(res,query(RC,mid+1,r,ql,qr));
return res;
}
bool chk(ll k){
for(ll i=2;i<=n;i++){
f[i]=query(1,1,n,max(1ll,i-k),i-1)+d[i];
mdf(1,1,n,i,f[i]);
}
return f[n]<=t;
}
int main(){
scanf("%lld %lld",&n,&t);
t-=n-1;
for(ll i=1;i<n;i++) scanf("%lld",&p[i]);
for(ll i=2;i<n;i++) scanf("%lld",&d[i]);
ll l=1,r=n-1;
while(l<r){
ll mid=(l+r)>>1;
if(chk(mid)) r=mid;
else l=mid+1;
}
for(ll i=l;i<n;i++) ans=min(ans,p[i]);
printf("%lld",ans);
}