求助,真的不行了
查看原帖
求助,真的不行了
183481
zyf1188楼主2020/12/25 22:06

我已经要疯了

单调队列做法

不知道为什么是错的

#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;
}

求大佬帮助。

2020/12/25 22:06
加载中...