P3957 跳房子[二分答案][dp][单调队列]

P3957 跳房子

前年pj没去年难好吧

首先要发现这个答案是有单调性的。

这个很显然了:氪金越多游戏越容易玩,氪金越少越难。

然而也有界限:如果所有正数的和加起来还不够需求,无解。

所以二分答案,考虑如何判定答案。

是人都知道要设一个\(dp[i]\)表示跳前\(i\)个房子的最大分数。

50pts就很简单的暴力转移:

\[dp[i]=max(dp[j]+a[i]),j < i,lim_1<dis[i]-dis[j] < lim_2\]

其实很大的暗示了:把\(a[i]\)拿出来就是:\(dp[i]=a[i]+max(dp[j])\)

单调队列走一波,维护滑动窗口最大值!



不得不说这里的单调队列很难写对。

我们弄一个指针\(j\),当我们求\(dp[i]\)的时候就移动\(j\)到最近。

然后当我们询问最大值的时候再考虑讨论退役人员的弹出,得到最大值。

代码:

#include<bits/stdc++.h>
using std::cin;
using std::cout;
using std::endl;
#define ll long long
const int maxn = 500005;
const int INF = 0x8f8f8f8f;
int a[maxn], dis[maxn];
int dp[maxn];
int n, d, k;
std::deque<int> q;// dan diao di jian
bool check(int g) {
    int lim1 = std::max(1, d - g), lim2 = d + g;
    memset(dp, 0x8f, sizeof dp);
    dp[0] = 0;
    q.clear();
    int j = 0;
    for(int i = 1; i <= n; i++) {
        /*for(int j = 0; j < i; j++) {
            if(dis[i] - dis[j] >= lim1 && dis[i] - dis[j] <= lim2) {
                dp[i] = std::max(dp[i], dp[j] + a[i]);
            }
        }*/
        while(j < i && dis[i] - dis[j] >= lim1) {
            if(dp[j] != INF) {
                while(!q.empty() && dp[q.back()] < dp[j]) q.pop_back();
                q.push_back(j);
            }
            j++;
        }
        while(!q.empty() && dis[i] - dis[q.front()] > lim2) q.pop_front();
        if(!q.empty()) dp[i] = dp[q.front()] + a[i];
    }
    int ans = 0x8f8f8f8f;
    for(int i = 1; i <= n; i++) ans = std::max(ans, dp[i]);// wrong here
    return ans >= k;
}
int main() {
    cin >> n >> d >> k;
    dis[0] = a[0] = 0;
    for(int i = 1; i <= n; i++) {
        cin >> dis[i] >> a[i];
    }
    int left = 0, right = std::max(dis[n], d), ans = -1;
    while(left <= right) {
        int mid = (left + right) >> 1;
        if(check(mid)) ans = mid, right = mid - 1;
        else left = mid + 1;
    }
    cout << ans << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/Garen-Wang/p/10381444.html

时间: 2024-10-08 10:37:15

P3957 跳房子[二分答案][dp][单调队列]的相关文章

习题:烽火传递(DP+单调队列)

烽火传递[题目描述]烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上.一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息:夜晚燃烧干柴,以火光传递军情.在某两座城市之间有n个烽火台,每个烽火台发出信号都有一定的代价.为了使情报准确的传递,在m个烽火台中至少要有一个发出信号.现输入n.m和每个烽火台发出的信号的代价,请计算总共最少需要花费多少代价,才能使敌军来袭之时,情报能在这两座城市之间准确的传递!!![输入描述]第一行有两个数n,m(1<=n,m<=1000000)分别表示n个烽火台

poj3017 dp+单调队列

http://poj.org/problem?id=3017 Description Given an integer sequence { an } of length N, you are to cut the sequence into several parts every one of which is a consecutive subsequence of the original sequence. Every part must satisfy that the sum of

bzoj 2806: [Ctsc2012]Cheat【广义SAM+二分+dp+单调队列】

把模板串建一个广义SAM 然后在线查询,每次在SAM上预处理出一个a[i]表示i位置向前最多能匹配多长的模板串 二分答案L,dp判断,设f[i]为·~i有几个匹配,转移显然是f[i]=max{f[i-1],f[j]+i-j(i-a[i]<=j<=i-L)},根据性质,i-a[i]是单调的(或者直接看a[i]的预处理过程也能看出来),所以这个dp可以用单调队列优化转移,最后判断是否f[n]>=L*0.9 #include<iostream> #include<cstdio

【BZOJ 2806】 2806: [Ctsc2012]Cheat (SAM+二分+DP+单调队列)

2806: [Ctsc2012]Cheat Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1262  Solved: 643 Description Input 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数接下来M行的01串,表示标准作文库接下来N行的01串,表示N篇作文 Output N行,每行一个整数,表示这篇作文的Lo 值. Sample Input 1 2 10110 000001110 1011001100 Sam

复习【dp+单调队列】

处理10W数据:二分答案+单调队列+dp 这题可以用二维Dp和一维Dp来做,虽然两者时间复杂度都是O(N2),但二维的无法被优化,一维的可以用单调队列将时间效率缩为O(N).因此构造Dp时优先采用纬度小的方案. 单调队列的核心模板见代码. ps:在一部分单调队列的题目中,队列各项的数值会同时变化.此时应用变量Plus做维护 #include <iostream> using namespace std; struct qnode { long tim, x; }; const long N=1

【贪心/DP/单调队列】【CF1029B】Creating the Contest

Description 给你一个单调不下降的长度为n的序列,请你找出一个最长的子序列,满足找出的子序列中,\(A_i<=A_{i-1}~\times~2\),其中i为下标,A为找出的子序列.对于一个长度为\(p\)的子序列,\(i~\in~[1,p-1]\). Input 两行,第一行是原序列的长度\(n\) 第二行是\(n\)个数,代表原序列中的\(n\)个数. Output 一行一个数,代表最长的长度 Sample Input 10 1 2 5 6 7 10 21 23 24 49 Samp

【烽火传递】dp + 单调队列优化

题目描述 烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上.一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息:夜晚燃烧干柴,以火光传递军情.在某两座城市之间有 n 个烽火台,每个烽火台发出信号都有一定的代价.为了使情报准确的传递,在 m 个烽火台中至少要有一个发出信号.现输入 n.m 和每个烽火台发出的信号的代价,请计算总共最少需要多少代价,才能使敌军来袭之时,情报能在这两座城市之间准确的传递! 输入格式 第一行有两个数 n,m 分别表示 n 个烽火台,在任意连续的 m 个烽火台中至少

BZOJ 2500 幸福的道路 树形DP+单调队列

题目大意:给定一棵树,令a[i]为从第i个节点出发的最长链,求a[i]中最长的区间,满足区间内最大值与最小值之差不超过m 读错题害死人,脑残害死人 求a[i]显然是树形DP 考虑从一个点出发的链可以从子节点走,也可以从父节点走 因此我们DP两次,第一次求出从子节点走的最长链,第二次求出从父节点走的最长链,两次取max就是答案 但是直接DP会有问题,因为从父节点走的最长链可能是从自己的子树出发的,这样就会走重 因此除记录从子节点出发的最长链外还要记录一个从另一个子节点出发的次长链,如果最长链长度相

台州 OJ 3847 Mowing the Lawn 线性DP 单调队列

描述 After winning the annual town competition for best lawn a year ago, Farmer John has grown lazy; he has not mowed the lawn since then and thus his lawn has become unruly. However, the competition is once again coming soon, and FJ would like to get