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[ir,i1]

求区间最值可以用线段树优化。

时间复杂度: 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

J. Distance on the tree

hello world&Restart the Journey