传送门

Description

跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一。

跳房子的游戏规则如下:

在地面上确定一个起点,然后在起点右侧画 $n$ 个格子,这些格子都在同一条直线上。每个格子内有一个数字(整数),表示到达这个 格子能得到的分数。玩家第一次从起点开始向右跳,跳到起点右侧的一个格子内。第二次再从当前位置继续向右跳,依此类推。规则规定:

玩家每次都必须跳到当前位置右侧的一个格子内。玩家可以在任意时刻结束游戏,获得的分数为曾经到达过的格子中的数字之和。

现在小 $R$ 研发了一款弹跳机器人来参加这个游戏。但是这个机器人有一个非常严重的缺陷,它每次向右弹跳的距离只能为固定的 $d$ 。小 $R$ 希望改进他的机器人,如果他花 $g$ 个金币改进他的机器人,那么他的机器人灵活性就能增加 $g$ ,但是需要注意的是,每 次弹跳的距离至少为 $1$ 。具体而言,当 $g<d$ 时,他的机器人每次可以选择向右弹跳的距离为 $d-g,d-g+1,d-g+2$ ,…, $d+g-2$ , $d+g-1$ , $d+g$ ;否则(当 $g \geq d$ 时),他的机器人每次可以选择向右弹跳的距离为 $1$ , $2$ , $3$ ,…, $d+g-2$ , $d+g-1$ , $d+g$ 。

现在小 $R$ 希望获得至少 $k$ 分,请问他至少要花多少金币来改造他的机器人。

Input

第一行三个正整数 $n$ , $d$ , $k$ ,分别表示格子的数目,改进前机器人弹跳的固定距离,以及希望至少获得的分数。相邻两个数 之间用一个空格隔开。

接下来 $n$ 行,每行两个正整数 $x_i,s_i$ ,分别表示起点到第 $i$ 个格子的距离以及第 $i$ 个格子的分数。两个数之间用一个空格隔开。保证 $x_i$ 按递增顺序输入。

Output

共一行,一个整数,表示至少要花多少金币来改造他的机器人。若无论如何他都无法获得至少 $k$ 分,输出 $-1$ 。

Hint

\(For~all:\)

\(1~\leq~n~\leq~500000~,~1~\leq~d~\leq~2000~,~1~\leq~x_i,k~\leq~10^9~,~|s_i|~\leq~10^5\)

Solution

这显然是个满足单调性的问题,于是考虑二分解决。

二分一个答案\(x\),那么即求出花费\(x\)的金币以后能得到的最大分数。考虑DP一波。

设\(f_i\)为跳到第\(i\)个格子的答案。从前面枚举上一个位置转移,时间复杂度\(O(n^2logn)\),期望得分\(50pts\)。

考虑每一个\(i\)的转移都是从同样长的区间转移来的,并且左端点单调不降。于是考虑使用单调队列优化DP,时间复杂度将至\(O(nlogn)\),期望得分\(100pts\)。

需要注意的是,在单调队列入队时,只能检查右端点是否符合要求,而不能检查左端点是否符合要求。检查左端点符合要求必须严格交给出队时检查,否则会导致入队指针卡在一个位置。

即:在入队时写成

while((pos < i) && ((MU[i].s-MU[pos].s) >= downfloor) && ((MU[i].s-MU[pos].s) <= upceil))

是不对的,因为最后一个条件检查了左端点是否符合要求。

while((pos < i) && ((MU[i].s-MU[pos].s) >= downfloor))

才是正确的写法。

Code

#include<cstdio>
#include<cstring>
#define rg register
#define ci const int
#define cl const long long typedef long long ll; template <typename T>
inline void qr(T &x) {
rg char ch=getchar(),lst=' ';
while((ch > '9') || (ch < '0')) lst=ch,ch=getchar();
while((ch >= '0') && (ch <= '9')) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
if(lst == '-') x=-x;
} namespace IO {
char buf[120];
} template <typename T>
inline void qw(T x,const char aft,const bool pt) {
if(x < 0) {x=-x,putchar('-');}
rg int top=0;
do {IO::buf[++top]=x%10+'0';} while(x/=10);
while(top) putchar(IO::buf[top--]);
if(pt) putchar(aft);
} template <typename T>
inline T mmax(const T a,const T b) {return a > b ? a : b;}
template <typename T>
inline T mmin(const T a,const T b) {return a < b ? a : b;}
template <typename T>
inline T mabs(const T a) {return a < 0 ? -a : a;} template <typename T>
inline void mswap(T &_a,T &_b) {
T _temp=_a;_a=_b;_b=_temp;
} const int maxn = 500010; int n,d,k,front,end;
int que[maxn];
ll frog[maxn]; struct M {
int s,v;
};
M MU[maxn]; bool check(int x); signed main() {
qr(n);qr(d);qr(k);
for(rg int i=1;i<=n;++i) {
qr(MU[i].s);qr(MU[i].v);
}
int r=100001,l=0,ans=-1,mid;
while(l <= r) {
mid=(l+r)>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
qw(ans,'\n',true);
return 0;
} bool check(ci x) {
memset(frog,0,sizeof frog);
que[front=end=1]=0;
rg int upceil = d+x,downfloor=mmax(1,d-x);
rg int pos=1;
for(rg int i=1;i<=n;++i) {
while((pos < i) && ((MU[i].s-MU[pos].s) >= downfloor)) {
while((front <= end) && (frog[que[end]] <= frog[pos])) --end;
que[++end]=pos++;
}
while((front <= end) && (((MU[i].s-MU[que[front]].s) > upceil))) ++front;
frog[i]=-1ll<<60;
if(front > end) continue;
if(MU[i].s-MU[que[front]].s < downfloor) continue;
frog[i]=frog[que[front]]+MU[i].v;
if(frog[i] >= k) return true;
}
return false;
}

Summary

在单调队列入队时只能检查右端点,出队时只能检查左端点。

【单调队列】【P3957】 跳房子的更多相关文章

  1. P3957 跳房子(二分答案+单调队列优化DP)

    题目链接:https://www.luogu.org/contestnew/show/4468 题目大意:跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一. 跳房子的游戏规则 ...

  2. 洛谷 P3957 跳房子 —— 二分答案+单调队列优化DP

    题目:https://www.luogu.org/problemnew/show/P3957 先二分一个 g,然后判断: 由于转移的范围是一个区间,也就是滑动窗口,所以单调队列优化: 可以先令队尾为 ...

  3. 2018.09.26洛谷P3957 跳房子(二分+单调队列优化dp)

    传送门 表示去年考普及组的时候失了智,现在看来并不是很难啊. 直接二分答案然后单调队列优化dp检验就行了. 注意入队和出队的条件. 代码: #include<bits/stdc++.h> ...

  4. 【P3957】跳房子(单调队列+DP+二分)

    终于把这个题缸出来了,话说这题也不是想的那么难... 因为最小的最大,所以二分,因为由前面推出后面,所以DP,因为输入单调,朴素DP会T,所以单调队列.要注意的是,这个题数据很大,要开LL,然后DP数 ...

  5. 【洛谷】2990:[USACO10OPEN]牛跳房子Cow Hopscotch【单调队列优化DP】

    P2990 [USACO10OPEN]牛跳房子Cow Hopscotch 题目描述 The cows have reverted to their childhood and are playing ...

  6. 洛谷P3975 跳房子 [DP,单调队列优化,二分答案]

    题目传送门 跳房子 题目描述 跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一. 跳房子的游戏规则如下: 在地面上确定一个起点,然后在起点右侧画 n 个格子,这些格子都在同一 ...

  7. NOIP2017 PJ 跳房子 —— 单调队列优化DP

    题目描述 跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一.跳房子的游戏规则如下: 在地面上确定一个起点,然后在起点右侧画n个格子,这些格子都在同一条直线上.每个格子内有一个 ...

  8. [NOIP2017普及组]跳房子(二分,单调队列优化dp)

    [NOIP2017普及组]跳房子 题目描述 跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一. 跳房子的游戏规则如下: 在地面上确定一个起点,然后在起点右侧画 nn 个格子, ...

  9. luogu P3657 (NOIP2017) 跳房子(二分+DP+单调队列)

    题面 传送门 分析 显然答案有单调性,可以二分答案,设当前二分值为g,根据题意我们可以求出跳跃长度的范围[l,r] 考虑DP 子状态: dp[i]表示跳到第i个点时的最大和 状态转移方程 \(dp[i ...

随机推荐

  1. Python单元测试--unittest(一)

    unittest模块是Python中自带的一个单元测试模块,我们可以用来做代码级的单元测试. 在unittest模块中,我们主要用到的有四个子模块,他们分别是: 1)TestCase:用来写编写逐条的 ...

  2. loadrunner12安装教程

    全套五个文件: 独立安装包,插件包,LR安装包,语言包,版本说明书 loadrunner 12安装教程 1.首先下载Loadrunner12安装包.下载下来将会有四个安装包. HP_LoadRunne ...

  3. [转]Git 撤销操作

    二. Git撤消操作 12.1 修改最后一次提交 git commit --amend 1.新建一个文件 2.提交一个之前的更改 3.跟踪这个文件 4.跟前一次一起提交 提示你是否重新编辑提交说明,如 ...

  4. 001 -js对时间日期的排序

    001-JS对时间日期的排序 最近在做公司的项目时间,产品给了一个很简单的页面,让帮忙写一下.首先看一下产品的需求: 需要对该列表进行排序 思路:(1)可以在数据库写sql语句的时间直接一个DESC按 ...

  5. 使用 Sublime Text 做 Javascript 编辑器 - 集成 JSHint 问题检测工具

    JSHint(jshint.com)是 Javascritp 代码质量工具,可以帮助开发人员发现 Javascript 代码中的错误和潜在的问题.jshint.com 是一个在线编辑器,我们可以为 S ...

  6. 第一次ScrumMeeting博客:团队任务分解

    团队任务分解 1. 主要任务 Alpha阶段结束后,我们要实现一个较为简陋的用户系统,并实现资源的上传和下载功能,完成"贡献点"相关内容并进行用户行为观察,以便Beta阶段完善.除 ...

  7. php序列化问题

    序列化是将变量转换为可保存或传输的字符串的过程:反序列化就是在适当的时候把这个字符串再转化成原来的变量使用.这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性. 1. serialize和 ...

  8. 王者荣耀交流协会final发布版本控制报告

    二次开发软件说明文档 Dec 6 纠正饼状图点击选择PSP文件无效. 添加饼状图丢失的代码. submit the files that last night I forgot. add shurum ...

  9. Alpha阶段中间产物——GUI Prototype、WBS及PSP

    作业地址:https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/1224 内容: GUI Prototype 我的书架 我的书架→添加图书 ...

  10. 软工实践第八次作业(课堂实战)- 项目UML设计(第五组)

    本次作业博客 团队信息 队名:起床一起肝活队 原组长: 白晨曦(101) 原组员: 李麒 (123) 陈德斌(104) 何裕捷(214) 黄培鑫(217) 王焕仁(233) 林志华(128) 乐忠豪( ...