老师准备把一筐智慧果分给班上的同学,第i个同学(从1开始编号)分到 \(a_i\) 个智慧果。Bonez (编号为1)是个自私的人,如果他的智慧果数不是班上最多的(即存在某位同学的智慧果数大于他的智慧果数),他会悄悄把别的同学的智慧果放进自己的那堆里。请问他至少需要从其他同学那里拿多少个智慧果,才可以使自己的智慧果数是班上最多的?
第一行为正整数n; 第二行为n个正整数a[1..n]。\((0 \le a_i \le 10^5)\)
60%的数据 \(1 \le n \le 100\).
100%的数据 \(1 \le n\le 100000\)
输出最少需要从别处拿的智慧果数。
3
1 8 0
4
\(n_1 : n_i \in U, \forall\ n_1 \ge n_i\) 换句话说, 就是要让 Bonez 的智慧果数量不少于任何一个同学.
这里我们给出一个例子.
若要让 Bonez 的智慧果数量最多, 那么遵循贪心的原则, 每一次我们都让智慧果数量最多的同学给 Bonez 一个智慧果.
这样看还是不太直观, 我们不妨按照智慧果数量排个序.
要使得 Bonez 的智慧果最多且操作次数最少, 我们则需要每次从智慧果最多的人那里拿出一个给 Bonez, 并且在该操作之后动态地维护智慧果序列. 直到 Bonez 成为智慧果数量最多的人. 操作的次数就是题目要求的答案.

在这个例子中, 我们不难看出, 算法的关键就是在于怎样每一次都可以快速的找到序列中最多智慧果的数量. 如何实现呢? 当然是优先队列.
在这个例子当中, 我们需要高效的知道当前序列中最多的智慧果数量是多少. 而优先队列正好可以满足我们的这个要求.
优先队列可以实现 O(1) 的查找最值. 若算上维护的操作, 那么一次查询和分配智慧果就是 O(1 + nlog n) = O(nlog n).
对于具体的优先队列实现这里就不再赘述.
为查找序列中的最大值, 本题使用的是大根堆, 并且以数组存储近似满二叉堆的形式存储堆.
给出近似满二叉堆的相关接口, 后续堆的操作有用到.
int _Parent(int x) { return ((x - 1) >> 1); }
int _LChild(int x) { return ((x << 1) + 1); }
int _RChild(int x) { return ((x << 1) + 2); }
题目中主要用到的操作只有两个分别是: 插入 和 修改
我们没办法直接知道待插入元素在堆中的正确位置, 所以我们要通过这种间接的方式先插入再维护, 从而完成一次堆插入操作.
将新插入的元素插入到堆的最底层, 即数组的最后一个位置, 使其成为一片新的叶子.
然后再沿着新插入的这个节点, 向根回溯. 每一次回溯都去判断当前节点及其两个子节点是否满足大根堆的结构.
若否, 则更新堆, 交换不符合的两个节点的位置, 使得在这个子堆中仍然保持着堆的结构.
不断回溯, 直到到达堆的根. 完成一次插入操作.
void insert(int n)
{
// 1. 插入新元素至堆底
_heap[_size++] = n;
// 2. 调整元素位置, 保持堆的结构
int buf, scan = _size - 1; // scan 从堆底开始扫描; buf 是 scan 的父节点用来判断堆结构是否正确
while ((buf = _Parent(scan)) >= 0) // 循环, 直到 scan 的父节点非零的时候退出
{
if (_heap[scan] < _heap[buf]) // 堆结构已经正确, 退出循环.
break;
swap(_heap[scan], _heap[buf]); // 交换节点, 使其满足堆的结构
scan = buf; // 更新 scan, 以继续向根节点迭代检查.
}
}
建树的过程就是不断地往优先队列中加入新的元素. 还是用上面提到的例子来演示, 如动图所示.

类似于插入操作的设计思想, 要对堆中的元素进行修改, 可以先直接修改, 然后再去维护堆.
将堆中最大元素, 即堆顶元素减一, Bonez 的智慧果数量加一. 完成对智慧果数量的修改
整体的思想和流程和insert()的基本一致. 不同的是在插入的过程中维护是自底向上的, 而在这次维护的过程中调整是自顶向下的.
具体来说, 先判断修改后的堆是否还维持着堆的结构.
int solve()
{
int ret = 0; // 记录分配的次数, 即 Bonez 拿到的智慧果数量
// 重分配智慧果
while (_head < _heap[0]) //循环, 直到 Bonez 的智慧果数量比堆中的最大元素还大
{
// 1. 进行一次智慧果分配
_heap[0]--; _head++; ret++;
// 2. 调整元素位置, 保持堆的结构
// 自顶向下遍历检查
// (这里的 buf 和之前的 buf 不同: buf 是 scan 中更大的子节点的下标)
for (int scan = 0, buf = 1; buf < _size; buf = _LChild(scan))
{
// 找出子节点中更大的那个
if (buf + 1 < _size && _heap[buf] < _heap[buf + 1]) // if (下标不越界 && 另一个子节点更大)
buf++;
if (_heap[scan] > _heap[buf]) // 堆结构已经正确, 退出循环.
break;
swap(_heap[scan], _heap[buf]); // 交换节点, 使其满足堆的结构.
scan = buf; // 更新 scan, 以继续向子节点迭代检查.
}
print();
}
还是刚才的那个例子. 下面是在优先队列中的演示.

#include <iostream>
using namespace std;
class BinaryHeap // 大根堆
{
int *_heap = nullptr; // 存储堆中的所有元素
int _size = 0; // 堆中元素的数量
int _capacity = 0; // 堆的最大容量
int _head; // Bonez 的智慧果数量
// 用数组实现近似满二叉堆的相关接口
int _Parent(int x) { return ((x - 1) >> 1); }
int _LChild(int x) { return ((x << 1) + 1); }
int _RChild(int x) { return ((x << 1) + 2); }
public:
// 初始化
BinaryHeap(int c = 100000) : _capacity(c) { _heap = new int[c + 100]; }
void init(int h) { _head = h; }
void insert(int n)
{
// 1. 插入新元素至堆底
_heap[_size++] = n;
// 2. 调整元素位置, 保持堆的结构
int buf, scan = _size - 1; // scan 从堆底开始扫描; buf 是 scan 的父节点用来判断堆结构是否正确
while ((buf = _Parent(scan)) >= 0) // 循环, 直到 scan 的父节点非零的时候退出
{
if (_heap[scan] < _heap[buf]) // 堆结构已经正确, 退出循环.
break;
swap(_heap[scan], _heap[buf]); // 交换节点, 使其满足堆的结构
scan = buf; // 更新 scan, 以继续向根节点迭代检查.
}
}
int solve()
{
int ret = 0; // 记录分配的次数, 即 Bonez 拿到的智慧果数量
// 重分配智慧果
while (_head < _heap[0]) //循环, 直到 Bonez 的智慧果数量比堆中的最大元素还大
{
// 1. 进行一次智慧果分配
_heap[0]--; _head++; ret++;
// 2. 调整元素位置, 保持堆的结构
// 自顶向下遍历检查
// (这里的 buf 和之前的 buf 不同: buf 是 scan 中更大的子节点的下标)
for (int scan = 0, buf = 1; buf < _size; buf = _LChild(scan))
{
// 找出子节点中更大的那个
if (buf + 1 < _size && _heap[buf] < _heap[buf + 1]) // if (下标不越界 && 另一个子节点更大)
buf++;
if (_heap[scan] > _heap[buf]) // 堆结构已经正确, 退出循环.
break;
swap(_heap[scan], _heap[buf]); // 交换节点, 使其满足堆的结构.
scan = buf; // 更新 scan, 以继续向子节点迭代检查.
}
print();
}
return ret;
}
void print()
{
for (int i = 0, j = 1; i < _size; i++)
{
if (i + 1 == j)
{
putchar('\n');
j *= 2;
}
printf("%d ", _heap[i]);
}
cout << endl;
}
};
inline int read();
int main(void)
{
#ifdef LOCAL_COMPILE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int numCount = read();
BinaryHeap heap(numCount);
heap.init(read());
for (int i = 1; i < numCount; i++)
heap.insert(read());
cout << heap.solve();
return 0;
}
inline int read()
{
int ret = 0, sign = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
sign = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
ret = (ret << 1) + (ret << 3) + (ch ^ 48);
ch = getchar();
}
return ret * sign;
}
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co
我正在尝试在Rails上安装ruby,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf