浅析拯救小矮人的 nlogn 算法及其证明
浅析拯救小矮人的 nlogn 算法及其证明
题型简介:
有 $ n $ 个人,第 $ i $ 个人身高 $ a_i $ 手长 $ b_i $ ,他们为了从一个高为 $ H $ 的洞中出去,决定搭人梯。如果一个人和他下面的人的身高之和加上他的手长可以达到洞的高度,那么他就可以出去。求最多有多少人能出去。 $ n\leq 10^6 $
算法流程
本题需要贪心,所以我们可以贪心到底。首先我们将所有人,按照他们的最低逃生高度 $ H-a_i-b_i $ 从高到低排序。一个必须要知道的结论:最低逃生高度越高的人,一定越先走。
首先我们将所有人按照 $ H-a_i-b_i $ (最低逃生高度)从高到低排序,根据结论越高的人越先走。然后如果是 $ n^2 $ 背包,就是对每个人做有条件的背包,模拟每个人是否能走。
而 $ n\times logn $ 的方法则是记录一个后缀 $ s[] $ ,其中 $ s[i] $ 表示第 $ i $ 个人后面最低逃生高度比他低的所有人的身高总和,然后用一个 $ tot $ 记录前面没有出去的人的身高总和,对于从高到低枚举的第 $ i $ 个人,如果 $ s[i]+tot>=H-a_i-b_i $ 就说明他能出去(于是默认他出去);否则就将这个人的身高和前面所有已经出去的人的身高作比较,如果当前这个人最高那么他就不出去了,不然就从前面已经出去的人里面找到那个最高的人,把他拉回洞里垫在下面,让当前这个人出去!照着这个过程做我们就能得到最优解。
算法证明:
其实这个算法只有两个待考究的地方,问题一:为什么最低逃生高度高的人,一定越先走?这个问题在很多题解里已经讨论过了,难以讲清,本题不做多讲,就用一张图感性一下:

本算法第二个问题在于这句话: 否则就将这个人的身高和前面所有已经出去的人的身高作比较,如果当前这个人最高那么他就不出去了,垫到下面去;不然就从前面已经出去的人里面找到那个最高的人,把他拉回洞里垫在下面,让当前这个人出去!为什么把上面最高的那个人拉下来,这个人就一定可以出去了?为什么只取一个人下来,我们可不可以拉多个人下来,让当前这个人出去的同时为后面的人垫高度?这个我们用两张图解读:


$ code: $
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define db double
#define rg register int
using namespace std;
int n,H; //人数;陷阱高度
int tot,ans; //之前没能逃生的人的身高总和;答案
int s[200005]; // s[i]表示在第i个人后面逃生的所有人的身高总和,就是后缀和
priority_queue<int> q; //用来求之前已经逃生的人中,身高最高的人
struct su{
int a,b,h,id; //身高,手长,最低逃生高度,编号
inline bool operator <(const su &i)const{
return h>i.h; //按最低逃生高度,从高到底排序
} //(其实说白了就是逃生能力排序,为了方便理解就详细一点)
}p[200005]; //存小矮人信息的数组 people
inline int qr(){ //快读
register char ch; register bool sign=0; rg res=0;
while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
if(sign)return -res; else return res;
}
int main(){
n=qr();
for(rg i=1;i<=n;++i)
p[i].a=qr(),p[i].b=qr();
H=qr();
for(rg i=1;i<=n;++i){
p[i].h=H-p[i].a-p[i].b; //最低逃生高度
p[i].id=i; //每个人的编号
}
sort(p+1,p+n+1);
for(rg i=n;i>=1;--i)
s[i]=s[i+1]+p[i+1].a; //s[i]表示在第i个人后面逃生的所有人堆起来达到的高度
for(rg i=1;i<=n;++i){
if(tot+s[i]>=p[i].h) q.push(p[i].a), ++ans;
//如果在他前面不能逃生的人加上在他后面的人堆起来达到了他的最低逃生高度,就让他走
else{
if(!q.empty()&&q.top()>p[i].a){ //拿出之前最大的身高和他对比,较大的走
tot+=q.top();
q.pop(); --ans;
q.push(p[i].a); ++ans; //其实ans根本没变,为了高度还原就这样了
} else tot+=p[i].a; //否则这个就垫到下面去
}
}printf("%d\n",ans);
return 0;
}
浅析拯救小矮人的 nlogn 算法及其证明的更多相关文章
- 【BZOJ-3174】拯救小矮人 贪心 + DP
3174: [Tjoi2013]拯救小矮人 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 686 Solved: 357[Submit][Status ...
- 2075 yh女朋友的危机、2544 拯救小矮人
Codevs2075和2544是一道题,直接A过. 2075 yh女朋友的危机 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 ...
- BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP
BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀 ...
- 【BZOJ3174】[TJOI2013]拯救小矮人(贪心,动态规划)
[BZOJ3174][TJOI2013]拯救小矮人(贪心,动态规划) 题面 BZOJ 洛谷 题解 我们定义一个小矮人的\(A_i+B_i\)为它的逃跑能力. 我们发现,如果有两个小矮人\(x,y\), ...
- 贪心+DP【洛谷P4823】 [TJOI2013]拯救小矮人
P4823 [TJOI2013]拯救小矮人 题目描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以 ...
- [luogu] P4823 [TJOI2013]拯救小矮人(贪心)
P4823 [TJOI2013]拯救小矮人 题目描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以 ...
- BZOJ3174. [TJOI2013]拯救小矮人(dp)
题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3174 题解 其实此题并不需要那么多YY的部分. 我们考虑若干个小矮人逃出的顺序.若跳出的 ...
- BZOJ3174 Tjoi2013 拯救小矮人(贪心+DP)
传送门 Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口.对于每一个 ...
- bzoj3174 [Tjoi2013]拯救小矮人
Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口.对于每一个小矮人, ...
随机推荐
- tomcat的work目录的作用
最近发现,很多网友喜欢把tomcat的work目录里的东西叫做缓存,其实那不是很恰当,work目录只是tomcat的工作目录,也就是tomcat把jsp转换为class文件的工作目录,这也正是为什么它 ...
- 【命令汇总】Windows 应急响应
日期:2019-06-07 16:11:49 作者:Bay0net 介绍:Windows 应急响应.取证及溯源相关内容学习记录 0x00.前言 常见的应急分类: web入侵:网页挂马.主页篡改.Web ...
- 将html转化为canvas图片(清晰度高)的方法
var copyDom = document.querySelector('.fenxiang1'); var width = copyDom.offsetWidth;//dom宽 var heigh ...
- Web UI自动化测试基础——元素定位(二)
本篇文章整理了元素定位的基础知识——多个元素定位方式. 一.多个元素定位方式简介 同单个元素定位方式相同,多个元素定位方式也有与之对应的8种方式,即id.name.class_name.tag_nam ...
- Linux 系统多台主机之间做SSH免密码登陆
SSH 免密登录 环境说明 CentOS 7.3 关键点 免密登录的关键点在于理解谁登录谁. A 生成的公钥给 B,也给 C.D,则 A 可以直接免密 SSH 登录 B.C.D A 生成密钥 在 A ...
- ECCV2014 Accepted paper
今天早上看到小伙伴们说ECCV2014结果出来了, 自己于是赶紧看了下, 感觉ECCV2014显著性的文章和以往的不太一样. 1.Salient Montages from Unconstrained ...
- Linux部署项目 shell脚本启动 及 Centos7开放指定端口
我们首先要在linux上安装好jdk tomcat mysql 这些基本环境,这些可以在楼主的 Linux入门 里面找到. linux部署spring项目 1. 右击项目,maven ...
- spring boot 枚举使用的坑2
上一篇说到在枚举当在controller的方法做参数时的坑,解决方法是配置了一个converter,后来想想,如果不闲每次都加一个注解麻烦的话,可以在参数前面加一个注解,添加一个解析器应该也可以解决这 ...
- MAC设置环境变量
1. Mac 启动加载文件位置(可设置环境变量) ------------------------------------------------------- (1)首先要知道你使用的Mac OS ...
- 【学习总结】快速上手Linux玩转典型应用-第7章-WebServer安装和配置讲解
课程目录链接 快速上手Linux玩转典型应用-目录 目录 1. Apache的安装 2. Apache的虚拟主机配置及伪静态操作 3. Nginx的基本操作 4. Nginx伪静态的实现 5. 实例演 ...