单调队列做法
不知道为什么是错的
#include<bits/stdc++.h>
using namespace std;
int n,d,k,dp[500005],q[500005],mid,l,r,a[500005],b[500005],t,h=1,c,j;//q数组存的是下标,a数组是分数,b是距离,dp存的是当前状况下这个点的最优解。
bool s(int g){
for(int i=1;i<=n;i++){
while(h<=t&&b[q[h]]<b[i]-d-g)h++;//弹出队列前端超出范围的。
c=min(b[i]-d+g,b[i]-1);//先计算出最右端能达到的位置。
for(;b[j]<=c;j++){
while(h<=t&&dp[q[t]]<=dp[j])t--;
q[++t]=j;
}//把所有符合条件的加入队列。因为一个格子只能加入队列一次,所以用全局变量j来记录加入到的位置。
if(h<=t)dp[i]=dp[q[h]]+a[i];
if(k<=dp[i])return 1;
}
return 0;
}
int main(){
cin>>n>>d>>k;
memset(dp,128,sizeof(dp));dp[0]=0;
for(int i=1;i<=n;i++)
scanf("%d%d",&b[i],&a[i]);
for(l=0,r=b[n],mid=b[n]>>1;l!=r;mid=(l+r)>>1){
if(s(mid))r=mid;
else l=mid+1;
memset(dp,128,sizeof(dp));//最小值。
h=1;t=0;//清除上一轮的影响。
j=0;dp[0]=0;//必须从零开始。
}//二分。
if(mid==b[n]&&!s(mid))cout<<-1;//判定是否能够达到目标分数
else cout<<mid;
return 0;
}
求大佬帮助。