版权声明:~~~感谢支持! https://blog.csdn.net/qq_39897867/article/details/88927648
题目
https://www.luogu.org/problemnew/show/P3957
解题思路
我们可以先二分答案。
然后,设
表示到第i个时的最优解,方程易得
但是对于
可以用单调队列优化一下就可以了。
注意在维护单调队列的单调性的时候,注意条件(找了我将近一个小时的bug)
代码
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N=500010;
int n,m,s,dis[N],a[N],l,r=N,tot,mid;
long long f[N],maxn;
bool dp(int k){
int L=m-k,R=m+k;
memset(f,0xcf,sizeof(f));
f[0]=0;
deque<int>q;
tot=0;
maxn=-1e16;
for (int i=1;i<=n;i++){
while (q.size()&&dis[i]-dis[q.front()]>R) q.pop_front();
while (dis[i]-dis[tot]>R&&i>tot) tot++;
while (dis[i]-dis[tot]>=L&&i>tot) {
while (q.size()&&f[q.back()]<f[tot]) q.pop_back();
q.push_back(tot); tot++;
}
if (q.size()) f[i]=f[q.front()]+(long long)a[i];
if (f[i]>maxn) maxn=f[i];
}
return maxn>=(long long)s;
}
int main(){
scanf("%d%d%d",&n,&m,&s);
for (int i=1;i<=n;i++)
scanf("%d%d",&dis[i],&a[i]);
while(l<=r){
mid=(l+r)/2;
if (dp(mid)) r=mid-1; else l=mid+1;
}
if (l>500000) printf("-1"); else printf("%d",r+1);
}