P3957 [NOIP2017 普及组] 跳房子

单调队列优化dp + 二分答案

#include<bits/stdc++.h>
using namespace std;
#define N 500005
#define inf 0x3f3f3f3f
#define LL long long
int n,d,k;
int x[N],v[N];
int q[N];
LL dp[N];
bool check(int cost){
    memset(dp,0xcf,sizeof(dp));
    dp[0]=0;
    int l=1,r=0;
    int lpos=max(1,d-cost);
    int rpos=d+cost;
    int cur=0;
    for(int i=1;i<=n;++i){
        while(cur<i && x[i]-x[cur]>=lpos) {
            while(l<=r&&dp[cur]>=dp[q[r]])--r;
            q[++r]=cur;
            ++cur;
        }
        while(l<=r&&x[i]-x[q[l]]>rpos) ++l;
        if(l<=r) dp[i]=dp[q[l]]+v[i];
        //cout<<dp[i]<<" "<<i<<" "<<l<<" "<<r<<endl; 
        if(dp[i]>=k) return true;
    }
  //  puts("");
    return false;
}
int main(){
    //freopen("1.in","r",stdin);
    scanf("%d%d%d",&n,&d,&k);
    for(int i=1;i<=n;++i)
        scanf("%d%d",&x[i],&v[i]);
    int ans=-1;
    int l=0,r=x[n];
    while(l<=r){
        int mid=(l+r)>>1;
        if(check(mid)){
            ans=mid;
            r=mid-1;
        }else l=mid+1;
    } 
   // check(0);
    printf("%d\n",ans); 
    return 0;
}

 

posted @ 2022-02-13 11:02  LikC1606  阅读(112)  评论(0)    收藏  举报