返回顶部

2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest J - Journey to the "The World's Start"

题意:一共n个站,首先处于第一个站的乘车点,在不用卷的情况下,会花一分钟时间到下一站i+1站下车点,同时要花d[i]分钟到i+1站的乘车点,在用卷的情况下,假如用的是第r张卷,可以从i搭到i-r到i+r范围内的所有站台,乘车时间不能省略,但是跑去乘车点的时间可以省略,第r张卷需要p[r]元,一张卷可以用多次,问买哪一张卷可以在t时间内到达第n个站台。
题解:因为用第r张卷的时间一定要大于等于用r+1张卷的时间,所有可以二分用哪张卷,设dp[i]为到达第i站乘车点用的最短时间,dp[i]可以由i-r到i-1的dp的最大值得到,用双指针维护一下递减序列,与i距离大于r的踢出,头部比dp[i]值小的踢出,最后可得到dp[n]
http://codeforces.com/gym/100801

#include<stdio.h>
#include<algorithm>
using namespace std;
#define LOCAL
#define ll long long
ll p[50100],d[50100];
ll dp[50100],que[50100];
ll n,t;
int check(int k){
	dp[1]=0;
	que[1]=1;
	int head=1,tail=1;
	for(int i=2;i<=n;i++){
		while(head>tail){
			if(i-que[tail]<=k)break;
			tail++;
		}
		dp[i]=dp[que[tail]]+d[i];
		while(head>=tail){
			if(dp[que[head]]<dp[i])break;
			head--;
		}
		que[++head]=i;
		//printf("que[head]=%d que[tail]=%d dp[%d]=%d\n",que[head],que[tail],i,dp[i]);
	}
	if(dp[n]+n-1>t)return 0;
	else return 1;
}
int main(){
	#ifdef LOCAL
    freopen("journey.in","r",stdin);
	freopen("journey.out","w",stdout);
#endif
	scanf("%lld %lld",&n,&t);
	for(int i=1;i<n;i++){
		scanf("%lld",&p[i]);
	}
	for(int i=2;i<n;i++)scanf("%lld",&d[i]);
	ll ans=n-1;
	ll l=1,r=n-1;
	//printf("%d\n",check(2));
	while(l<=r){
		int mid=(l+r)/2;
		if(check(mid)==1){
			ans=mid;
			r=mid-1;
		}
		else{
			l=mid+1;
		}
	}
	ll res=100010;
	for(int i=ans;i<n;i++)res=min(res,p[i]);
	printf("%lld\n",res);
}
posted @ 2020-11-18 20:04  League-of-cryer  阅读(110)  评论(0)    收藏  举报