Journey to the “The World’s Start”(二分+dp+单调队列)
推荐阅读:https://www.cnblogs.com/hua-dong/p/9460761.html
题意: 现在有1,2,3...N这N个站, 给定限定时间Limt, N-1种票的价格, 分别对应一个最远距离, 叫你选择一种票, 满足可以在规定时间到达N站台,而且价格最低
思路: 如果买距离为L的票可以在规定时间到,那么距离>L的票也一定能到. 我们只需要二分出这个下界 L,然后在>=L里选择一个最低价格即可. 二分里面用单调队列优化. 复杂度O(NlgN).
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+100;
ll n,t;
ll p[maxn];
ll d[maxn];
ll q[maxn];
ll dp[maxn];
int check( int r )
{
int tail = 1;
int head = 1;
q[head] = 1;
dp[1] = 0;
for ( int i=2; i<=n; i++ ) {
while ( tail<head && i-q[tail]>r ) {
tail ++;
}
dp[i] = dp[ q[tail] ] + d[i];
q[++head] = i;
while ( tail<head && dp[ q[head] ]<=dp[ q[head-1] ] ) {
q[ head-1 ] = q[head];
head --;
}
}
return dp[n]<=t;
}
int main()
{
freopen("journey.in","r",stdin);
freopen("journey.out","w",stdout);
ll i,j;
cin >> n >> t;
t -= (n-1);
for ( i=1; i<n; i++ ) {
cin >> p[i];
}
for ( i=2; i<n; i++ ) {
cin >> d[i];
}
d[n] = 0;
ll ans,mid;
ll left = 1;
ll right = n-1;
while ( left<=right ) {
mid = (left+right)/2;
if ( check(mid)==1 ) {
ans = mid;
right = mid-1;
}
else {
left = mid+1;
}
}
ll minn = p[ans];
for ( i=ans+1; i<n; i++ ) {
minn = min(p[i],minn);
}
cout << minn << endl;
return 0;
}