[NOIP2017 普及组] 跳房子 - 洛谷
核心思路
单调队列优化dp
顺序
先让合法答案入队
再删去越界答案
判断非空 后 求 答案
一个答案合法 当且仅当 l <= dis <= r
记
调了n久,找题解调。
竟发现几乎没有用 STL deque 的。
故写了个青春版题解。
AC 代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5+10;
int f[N],a[N];
int d,k;
int n;
int x[N];
deque<int> q;
int ct(int mid){
int l = max(1LL,d-mid),r = d+mid;//
//l <= xi-xj <= r
int j = 0;
q.clear();
memset(f,-0x3f,sizeof(f));
int ans = 0;
f[0] = 0;
for(int i = 1;i <= n;i++){
while(j < i&&l <= x[i]-x[j]){
// cout<<j<<" "<<i<<endl;
while(!q.empty()&&f[q.back()] < f[j])q.pop_back();
q.push_back(j);
j++;
}
while(!q.empty()&& x[i]-x[q.front()] > r){
// cout<<"out "<<q.front()<<endl;
q.pop_front();
}
if(!q.empty())f[i] = f[q.front()]+a[i];
// cout<<i<<" ans "<<f[i]<<endl;
ans = max(ans,f[i]);
}
return ans;
}
int find(int l,int r){
while(l <= r){
int mid = (l+r)/2;
//cout<<mid<<" "<<ct(mid)<<" "<<(ct(mid) >= k)<<endl;
if(ct(mid) >= k)r = mid-1;
else l = mid+1;
}
return l;
}
signed main(){
cin>>n>>d>>k;
for(int i = 1;i <= n;i++){
cin>>x[i]>>a[i];
}
if(find(0,1e9+7) > 1e9){
cout<<-1;
return 0;
}
cout<<find(0,x[n]+1);
return 0;
}