浅析拯救小矮人的 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 $ 就说明他能出去(于是默认他出去);否则就将这个人的身高和前面所有已经出去的人的身高作比较,如果当前这个人最高那么他就不出去了,不然就从前面已经出去的人里面找到那个最高的人,把他拉回洞里垫在下面,让当前这个人出去!照着这个过程做我们就能得到最优解。


算法证明:

其实这个算法只有两个待考究的地方,问题一:为什么最低逃生高度高的人,一定越先走?这个问题在很多题解里已经讨论过了,难以讲清,本题不做多讲,就用一张图感性一下:

nH0bV0.png

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

nH0XPU.png

nHBmMd.png



$ 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 intusing 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]; //存小矮人信息的数组 peopleinline 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;
}

转载于:https://www.cnblogs.com/812-xiao-wen/p/11545341.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/262702.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android Material Design TabLayout属性app:tabMode和app: tabGravity

Android Material Design TabLayout属性app:tabMode和app: tabGravity Android Material Design 中的TabLayout有两个比较有用的属性 app:tabMode、app:tabGravity&#xff0c; &#xff08;1&#xff09;app:tabMode有两个值&#xff1a;fixed和scrollable。 &#xff08;2&am…

IE 中的一些脚本问题

1. input name 不支持这样写:var oInput document.createElement("input");oInput.name "MyName";这样写无用, 应该写:var oInput document.createElement("<input nameMyName >");2. 严格定义的XHTML标准的一些问题.假设层关系为:1>…

UVA 567 - Risk

最短路问题&#xff1a;floyd算法&#xff1a; 注意&#xff1a;输出格式 #include<stdio.h> #define MAXN 200int a, b, n, d[30][30], num; void init() {num 0;while(scanf("%d",&a) 1){for(int i 1; i < 20; i )for(int j 1; j < 20; j )if(…

unity混音

前言在游戏中&#xff0c;通常我们需要控制整个游戏的主音量&#xff08;全局音量&#xff09;&#xff0c;并且单独控制背景音乐和其他音效&#xff08;攻击、爆炸之类&#xff09;的音量&#xff0c;这时我们可以用Audio Mixer来解决。 如果文章中有哪些地方写的不对&#xf…

一个较完整的关键字过滤解决方案(上)

如果您希望看到关键字过滤算法的话那么可能就要失望了。博客园中已经有不少关于此类算法的文章&#xff08;例如这里和这里&#xff09;&#xff0c;虽然可能无法直接满足特定需求&#xff0c;但是已经足够作为参考使用。而本文的目的&#xff0c;是给出一个较为完整的关键字过…

核能力将定手机浏览器HTML5之争成败

目前&#xff0c;国内手机浏览器市场竞争异常激烈&#xff0c;UC、腾讯、欧朋、海豚等各大手机浏览器品牌频频亮出各自的HTML5跑分一比高下。然而各大厂商的HTML5功力到底有多深却众说纷纭&#xff0c;能否迅速适应对HTML5的支持&#xff0c;对厂商来说面临的可能是实力的巨大挑…

【转】Thunderbird中配置签名

原文网址&#xff1a;https://support.mozilla.org/zh-CN/kb/Thunderbird%E4%B8%AD%E9%85%8D%E7%BD%AE%E7%AD%BE%E5%90%8D “签名”是一块自动附加到每个您发出的消息的文字&#xff08;包括新消息和对收到消息的回复&#xff09;。他们通常用来提供与每个消息有关的附加联系信…

base css

body,ul,ol,dt,dd,img,p,h1,h2,h3,h4,h5,h6,input,textarea,select,fieldset,legend,ul,ol,dl,th{margin: 0;padding: 0; } body {font-family: "微软雅黑";color: #333; } input,img{border: 0;outline: none; } img {display: block; } ul,ol,li{list-style: none …

Windows下的常用的DOS命令

用的DOS命令。 1.dir dir是英文单词directory(目录&#xff09;的缩写&#xff0c;主要用来显示一个目录下的文件和子目录。 [功能]显示指定磁盘、目录中的文件和子目录信息&#xff0c;包括文件及子目录所在磁盘的卷标、文件与子目录的名称、每个文件的大小、文件及目录建立的…

依赖注入Bean属性——手动装配Bean

一、构造方法注入 其中&#xff0c;可以根据不同的参数列表调用不同的重载的构造方法&#xff1b; 其中&#xff0c;基本数据类型没有包&#xff0c;引用类型都有包路径&#xff0c;基本类型对应封装类&#xff1b; 二、通过property标签调用类的set方法注入 三、通过p命名空间…

ADO.NET数据库

ASP.NET提供了ADO.NET技术&#xff0c;它是ASP.NET应用程序与数据库进行交互的一种技术。 ADO.NET技术把对数据库的操作分为几个步骤&#xff0c;并为每个步骤提供对象来封装操作过程&#xff0c;从而使对数据库的操作变得简单易行。 ADO.NET组件通过以下两个主要的组件将数据访…

获取滚动文本框TextArea焦点位置信息

//输入参数&#xff1a;// _mOffset 滚动文本框对象//返回值:// OffsetObject 位置信息对象// length 焦点位置长度// leftValue 滚动文本框从开始到焦点所在位置的文本值// rightValue 滚动文本框从焦点位置到结束的文本值// scrollTop 滚动框位置//更新记录:// 2…

十天学会ASP.Net——(2)

2.Web控件 1&#xff09;WebControl基类属性 参考http://msdn.microsoft.com/zh-cn/library/7zt8s89c 2&#xff09;Form控件&#xff08;很简单&#xff09; 应用&#xff1a;实现如下效果 <form id"form1" runat"server"> <div> 班级:<br…

Spring表达式

一、SpEL 其中&#xff0c;直接写也可以赋值&#xff0c;‘ ’ 单引号引起来后成为一个字符串对象&#xff0c;可以调用String的方法&#xff1b; 二、引用另外一个bean 装配这个类的bean&#xff1a; 1、第一种方法&#xff0c;property标签中使用bean引用 2、使用Spring表达…

sama5d3 环境检测 gpio--yk测试

说明:  &#xff47;&#xff50;&#xff49;&#xff4f;的&#xff2d;&#xff21;&#xff30;关系 yk0--pioA7 yk1--pioA5 yk2--pioA9 yk3--pioA3 yk4--pioA1 yk5--pioA8 (端子从左&#xff0d;&#xff0d;&#xff1e;右 QD--pioA21内部总启动信号&#…

【Vegas原创】X connection to localhost:11.0 broken (explicit kill or server shutdown)解决方法...

以oracle 进入系统&#xff08;不要使用su切换到oracle&#xff09; 执行env 显示 DISPLAYlocalhost:10.0 执行dbca &#xff0c;出现图形界面 转载于:https://www.cnblogs.com/amadeuslee/archive/2009/01/04/3744408.html

关于偏微分

在图像处理里面&#xff0c;偏微分主要体现在能量极小化上面&#xff0c;而这种极小化泛函往往包含变量的微分&#xff0c;所以只要掌握Euler-Lagrange方程就可以知道其演化方程了&#xff0c;而这个方程就是极小化能量泛函的解。辅以梯度下降法之类的迭代策略&#xff0c;和离…

集合属性注入值

一、集合注入&#xff0c;装配bean的时候&#xff0c;即在xml中添加bean的时候 1、List集合 2、set集合&#xff0c;无序&#xff0c;即无索引&#xff0c;所以也无重复&#xff0c; 3、map key-value键值对双列集合&#xff0c;内置接口Entry 4、Properties集合&#xff0c;可…

用C/C++实现倒序输出,以12345为例

用C/C语言实现倒序输出12345,代码如下#include <stdio.h>int main(){ int i12345; int b; for(;i>1;ii/10) { bi%10; printf("%d",b); } return 0;}转载于:https://blog.51cto.com/cheng618/1701515

QuerySyntax(查询语法)

Code/// <summary>/// QuerySyntax&#xff08;查询语法&#xff09;的摘要说明/// </summary>public class QuerySyntax { public int ID { get; set; } public string Name { get; set; } public void QuerySyntaxTest() { List<Quer…