J. Journey to the “The World’s Start”(二分线段树dp)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了J. Journey to the “The World’s Start”(二分线段树dp)相关的知识,希望对你有一定的参考价值。
J. Journey to the “The World’s Start”(二分线段树dp)
显然卡的范围 r r r是可以二分的,如果 r 1 < r 2 r_1< r_2 r1<r2 , r 1 r_1 r1 能满足显然 r 2 r_2 r2也能满足。
然后考虑对于某个 r r r,能否在 t t t内到达 n n n。
这可以通过dp。
显然由状态转移方程: d p i = m a x ( d p j ) + t i , j ∈ [ i − r , i − 1 ] dp_i=max(dp_j)+t_i ,j\\in [i-r,i-1] dpi=max(dpj)+ti,j∈[i−r,i−1]
求区间最值可以用线段树优化。
时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=5e4+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0)
void Print(int *a,int n){
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\\n",a[n]);
}
//区间修改 区间求和
#define il inline
#define lx x<<1
#define rx x<<1|1
#define len(x) (a[x].r-a[x].l+1)
struct node{
int l,r;
ll s;
}a[N<<2];
il void re(int x){
a[x].s=min(a[lx].s,a[rx].s);
}
il void bud(int x,int l,int r){
a[x].l=l,a[x].r=r,a[x].s=1e18;
if(l==r){
return;
}
int m=(l+r)>>1;bud(lx,l,m),bud(rx,m+1,r);
re(x);
}
il void upd(int x,int p,ll v){
if(a[x].l==a[x].r){
a[x].s=v;return;
}
int m=a[x].l+a[x].r>>1;
if(p<=m) upd(lx,p,v);
else upd(rx,p,v);
re(x);
}
il ll que(int x,int l,int r){
if(a[x].l>=l&&a[x].r<=r) return a[x].s;
int m=(a[x].l+a[x].r)>>1;ll ans=1e18;
if(l<=m) ans=min(ans,que(lx,l,r));
if(r>m)ans=min(ans,que(rx,l,r));
return ans;
}
int p[N],b[N];
int n,t;
bool ck(int r){
upd(1,1,0);
ll x;
for(int i=2;i<=n;i++){
x=que(1,max(1,i-r),i-1)+b[i];
upd(1,i,x);
}
return x<=t;
}
int main(){
freopen("journey.in","r",stdin);
freopen("journey.out","w",stdout);
scanf("%d%d",&n,&t);t-=n-1;
for(int i=1;i<n;i++) scanf("%d",&p[i]);
for(int i=n-2;i;i--) p[i]=min(p[i],p[i+1]);
for(int i=2;i<n;i++) scanf("%d",&b[i]);
int ans=inf,l=1,r=n-1;bud(1,1,n);
while(l<=r){
int m=l+r>>1;
if(ck(m)) ans=min(ans,p[m]),r=m-1;
else l=m+1;
}
printf("%d\\n",ans);
return 0;
}
以上是关于J. Journey to the “The World’s Start”(二分线段树dp)的主要内容,如果未能解决你的问题,请参考以下文章
The Go Blog Getting to Go: The Journey of Go's Garbage Collector
The 2019 China Collegiate Programming Contest Harbin Site J. Justifying the Conjecture
HB限时领Deponia: The Complete Journey
[Journey with golang] 0. Planning for the New year and new journey