zoukankan      html  css  js  c++  java
  • [题解]luogu_P3957跳房子(单调队列

    虽然是道普及的题,一眼看出二分单调队列,但是我不会写单调队列

    不能再套板子了,必须要理解灵活

    用一个指针j维护窗口的右端点,每次移动时把多出来那部分的扫一下塞进去,取队头前把左端点左边的弹掉

    各种算法都没有完全固定的写法!

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=500009;
    int n,d,k;
    int s[maxn],q[maxn];
    ll x[maxn],f[maxn];
    bool check(int g){
        for(int i=0;i<=n;i++)f[i]=-1e18;
        int hd=1,tl=0,j=0;
        q[1]=0;f[0]=0;
        int l=max(d-g,1),r=d+g;
        
        for(int i=1;i<=n;i++){
            while(x[i]-l>=x[j]&&j<i){
                if(f[j]!=-1e18){
                    while(hd<=tl&&f[q[tl]]<=f[j])tl--;
                    q[++tl]=j;
                }
                j++;
            }
            while(hd<=tl&&x[i]-r>x[q[hd]])hd++;
            if(hd<=tl)f[i]=f[q[hd]]+s[i];
            if(f[i]>=k)return 1;
        }
        return 0;
    }
    int main(){
        scanf("%d%d%d",&n,&d,&k);
        for(int i=1;i<=n;i++)scanf("%d%d",&x[i],&s[i]);
        int l=0,r=x[n];
        while(l<r){
            int mid=(l+r)>>1;
            if(check(mid))r=mid;
            else l=mid+1;
        }
        if(check(l))printf("%d",l);
        else printf("-1");
    }
  • 相关阅读:
    汉诺塔
    破损的键盘
    解方程
    运输计划
    选学霸
    子集和的目标值
    棋盘染色2
    守卫者的挑战
    飞扬的小鸟
    攻克城堡
  • 原文地址:https://www.cnblogs.com/superminivan/p/11595669.html
Copyright © 2011-2022 走看看