2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest J - Journey to the "The World's Start"
阿新 • • 發佈:2020-11-18
題意:一共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); }