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
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/hua-dong/p/9460761.html