洛谷P3957 跳房子 题解 二分答案/DP/RMQ
题目链接:https://www.luogu.org/problem/P3957
这道题目我用到了如下算法:
- 线段树求区间最大值;
- 二分答案;
- DP求每一次枚举答案g时是否能够找到 \(\ge k\) 的解法。
我们一开始用 \(x[i]\) 和 \(s[i]\) 来表示到起点的距离以及第 \(i\) 个点的分值。
与此同时我们还要算上我们的起点,它满足性质 \(x[0] = s[0] = 0\) ,我们接下来的判断都是建立在这 \(1 + n\) 个点的基础上的。
check(g)
首先,我们假设 \(g\) 已经确定的情况下,如何判断是否有行走方案能够累计到 \(\ge k\) 。
这一步需要用到DP思想,我们定义状态 \(f[i]\) 表示从起点到第 \(i\) 个点所能够积累的最大分值,那么,状态转移方程为:
\(f[i] = \max( f[j] )\) ,其中 \(j\) 满足 \(x[i]-d-g \le x[j] \le \min( x[i]-1, x[i]-d+g )\)
并且我们可以发现这个范围的 \(j\) 必定在一个连续的区间 \([L, R]\) 内,所以我们可以用二分(lower_bound 及 upper_bound 函数来快速获得 \(L\) 和 \(R\) 。
然后我们需要知道区间 \([L,R]\) 范围内 \(x[j]\) 的最大值,这一步过程我是使用线段树来实现的(因为这里涉及单点更新及区间最值)。
二分答案
在编写完 check(g) 函数之后,我们便可以在区间 \([0, x[n] ]\) 范围内进行二分,进而找到满足要求的最小的答案。
实现代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 500050;
int n, d, k, x[maxn], s[maxn], f[maxn];
#define lson l, mid, (rt<<1)
#define rson mid+1, r, (rt<<1|1)
#define inf (1<<29)
int maxv[maxn<<2];
void sg_push_up(int rt) {
    maxv[rt] = max(maxv[rt<<1], maxv[rt<<1|1]);
}
void sg_build(int l, int r, int rt) {
    if (l >= r) maxv[rt] = -inf;
    else {
        int mid = (l + r) / 2;
        sg_build(lson);
        sg_build(rson);
        sg_push_up(rt);
    }
}
void sg_update(int p, int v, int l, int r, int rt) {
    if (l == r) maxv[rt] = v;
    else {
        int mid = (l + r) / 2;
        if (p <= mid) sg_update(p, v, lson);
        else sg_update(p, v, rson);
        sg_push_up(rt);
    }
}
int sg_query(int L, int R, int l, int r, int rt) {
    if (L <= l && r <= R) return maxv[rt];
    int mid = (l + r) / 2, tmp = -inf;
    if (L <= mid) tmp = max(tmp, sg_query(L, R, lson));
    if (R > mid) tmp = max(tmp, sg_query(L, R, rson));
    return tmp;
}
bool check(int g) {
    sg_build(0, n, 1);
    sg_update(0, 0, 0, n, 1);
    for (int i = 1; i <= n; i ++) {
        f[i] = -inf;
        int lid = lower_bound(x, x+i, x[i]-d-g) - x;
        int rid = upper_bound(x, x+i+1, min(x[i]-1, x[i]-d+g)) - x - 1;
        if (lid <= rid) {
            int tmp = sg_query(lid, rid, 0, n, 1);
            if (tmp != -inf) {
                f[i] = tmp + s[i];
                if (f[i] >= k) return true;
                sg_update(i, f[i], 0, n, 1);
            }
        }
    }
    return false;
}
int main() {
    cin >> n >> d >> k;
    for (int i = 1; i <= n; i ++) cin >> x[i] >> s[i];
    int L = 0, R = x[n], res = -1;
    while (L <= R) {
        int mid = (L + R) / 2;
        if (check(mid)) { res = mid; R = mid-1; }
        else L = mid + 1;
    }
    cout << res << endl;
    return 0;
}
作者:zifeiy
洛谷P3957 跳房子 题解 二分答案/DP/RMQ的更多相关文章
- 2018.09.26洛谷P3957 跳房子(二分+单调队列优化dp)
		传送门 表示去年考普及组的时候失了智,现在看来并不是很难啊. 直接二分答案然后单调队列优化dp检验就行了. 注意入队和出队的条件. 代码: #include<bits/stdc++.h> ... 
- 洛谷P3957 跳房子(Noip2017普及组 T4)
		今天我们的考试就考到了这道题,在考场上就压根没有思路,我知道它是一道dp的题,但因为太弱还是写不出来. 下来评讲的时候知道了一些思路,是dp加上二分查找的方式,还能够用单调队列优化. 但看了网上的许多 ... 
- 洛谷 P3957 跳房子 —— 二分答案+单调队列优化DP
		题目:https://www.luogu.org/problemnew/show/P3957 先二分一个 g,然后判断: 由于转移的范围是一个区间,也就是滑动窗口,所以单调队列优化: 可以先令队尾为 ... 
- P3957 跳房子(二分答案+单调队列优化DP)
		题目链接:https://www.luogu.org/contestnew/show/4468 题目大意:跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一. 跳房子的游戏规则 ... 
- 洛谷P3957 跳房子
		普及组的题.....填坑来了. 当年的我一眼二分+DP,现在都佩服起自己来了...... 然后我们就写个二分,在check里面写单调队列优化DP即可. 然后就A了...... #include < ... 
- 洛谷 P3957 跳房子
		https://www.luogu.org/problemnew/show/P3957 错误记录:1.没开longlong 2. -inf不够小 #include<cstdio> #inc ... 
- 洛谷 P1800 software_NOI导刊2010提高(06)(二分答案+DP检验)
		P1800 software_NOI导刊2010提高(06) 标签 二分答案 难度 普及/提高- 题目描述 一个软件开发公司同时要开发两个软件,并且要同时交付给用户,现在公司为了尽快完成这一任务,将每 ... 
- 洛谷NOIp热身赛题解
		洛谷NOIp热身赛题解 A 最大差值 简单树状数组,维护区间和.区间平方和,方差按照给的公式算就行了 #include<bits/stdc++.h> #define il inline # ... 
- 洛谷 P4072 [SDOI2016]征途 斜率优化DP
		洛谷 P4072 [SDOI2016]征途 斜率优化DP 题目描述 \(Pine\) 开始了从 \(S\) 地到 \(T\) 地的征途. 从\(S\)地到\(T\)地的路可以划分成 \(n\) 段,相 ... 
随机推荐
- 解决IE6、IE7、Firefox兼容最简单的CSS Hack
			写三句代码来控制一个属性,区别Firefox,IE7,IE6: background:orange; *background:green !important; *background:blue; ... 
- NFS实现(双httpd + php-fpm + nfs + mysql 搭建discuz论坛)的方法
			NFS相关介绍 一.NFS简介 1. NFS(Network File System):NFS是一个文件共享协议, 也是是在类Unix系统中在内核中实现的文件系统. 2. 起源:最早是由SUN公司研发 ... 
- vagrant up 时提示错误 cound not open file
			根据教程:https://laravel-china.org/docs/laravel-development-environment/5.5/development-environment-wind ... 
- 链表经典题Merge Two Sorted Lists
			Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ... 
- Python对于封装性的看法
- PHPCMS快速建站系列之在线留言
			有两种方法 第一种方法: 利用留言板插件,在后台模板中,安装留言板插件使用,这里先不展开. 第二种方法: 表单向导的适用场合: 如果一个前台页面只是为了提交表单数据,那么就非常适合适用表单向导的功能, ... 
- Kubernetes Ingress日志分析入门
			本文主要介绍如何基于日志服务构建Kubernetes Ingress日志分析平台,并提供一些简单的动手实验方便大家快速了解日志服务相关功能. 部署Ingress日志方案 登录容器服务管理控制台. 将上 ... 
- 解决:"UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position"错误
			版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/Haiyang_Duan/article/ ... 
- Apple的App Analytics统计平台你必须知道的
			Apple最近在iTunesConnect里最新发布了App Analytics统计平台,提供了现有友盟统计平台和自有统计平台无法统计的数据,具有自己的独有特点,尤其是下面几个最让人头疼的流量分析转化 ... 
- Extended Traffic
			题目链接 题意:有n个路口,m条通路,如果经过一条路则会得到(终点 - 起点)^3的权值,求从1点到其他点的最小权值,如果权值小于3或无法到达输出'?'. 题解:因为权值可能为负,所以用SPFA来解题 ... 
