Gym 100801J Journey to the "The World's Start"(二分+单调队列)
题意: 现在有1,2,3...N这N个站, 给定限定时间Limt, N-1种票的价格, 分别对应一个最远距离, 叫你选择一种票, 满足可以在规定时间到达N站台,而且价格最低
思路: 如果买距离为L的票可以在规定时间到,那么距离>L的票也一定能到. 我们只需要二分出这个下界 L,然后在>=L里选择一个最低价格即可. 二分里面用单调队列优化. 复杂度O(NlgN).
(注意可能爆 long long
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=100010; ll p[maxn],t[maxn],q[maxn],dp[maxn],head,tail,N,Limit; bool check(ll L) { head=tail=1; q[head]=1; dp[1]=0; for(int i=2;i<=N;i++){ while(tail<head&&i-q[tail]>L) tail++; dp[i]=dp[q[tail]]+t[i]; q[++head]=i; while(tail<head&&dp[q[head]]<=dp[q[head-1]]) q[head-1]=q[head],head--; } return dp[N]<=Limit; } int main() { int i; scanf("%I64d%I64d",&N,&Limit); Limit-=(N-1); for(i=1;i<N;i++) scanf("%d",&p[i]); for(i=2;i<N;i++) scanf("%d",&t[i]); ll L=1,R=N-1,Mid,Mn=1; while(L<=R){ Mid=(L+R)/2; if(check(Mid)) Mn=Mid,R=Mid-1; else L=Mid+1; } ll ans=p[Mn]; for(i=Mn+1;i<N;i++) ans=min(p[i],ans); printf("%I64d\n",ans); return 0; }
It is your time to fight!