Codeforces 1329C - Drazil Likes Heap(堆+贪心)
题意
给出一个高度为 h 的大根堆, 要求弹出其中若干个数后高度变为 g, 并且变化前后大根堆都是满二叉树. 问新的大根堆所有数之和的最小值, 并要给出一种弹出数的操作序列(节点序号). h, g ≤ 20. 堆的弹出过程见如下代码:
题解
考虑新堆的每个节点的可能最小结果: 如果是叶子节点, 那么最小是取它的子树中最小的数; 否则, 取子树中比两个儿子大的数中的最小值.
那么, 能否能得到这个每个节点都取到最小值的堆呢, 回答是肯定的. 我们在得知哪些数字会留下后, 是要把其他点弹出的. 弹出这些数后, 我们还需要考虑新堆是不是满二叉树. 按序号从小到大考虑每个节点, 会发现(这个过程不太好描述, 主要还是堆的性质)每个节点最后的结果一定是以它为根的子树中剩余数字的最大值(被祖先节点使用的话是要移除的), 既然每个节点都有数字, 这个堆自然是满二叉堆.
要得到新堆的每个节点的数字, 可以从下到上维护每个节点的子树的序列. 每次合并都是 O(len) (len为序列长度) 的, 总的时间复杂度为 O(nlogn). 要输出操作序列时, 可以从下往上弹出不需要的数字, 这样不会影响到祖先的结构.
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inc(i, l, r) for (int i = l; i <= r; i++)
#define dec(i, l, r) for (int i = l; i >= r; i--)
const int maxn = (1 << 20) + 5;
int t, h, g;
int val[maxn], nxt[maxn];
vector<int> sub[maxn];
inline vector<int> Merge(vector<int> v1, vector<int> v2, int id) {
int sz1 = v1.size(), sz2 = v2.size();
vector<int> r(sz1 + sz2 + 1);
for (int i = 0, j = 0; i + j < sz1 + sz2;) {
if (j == sz2 || i < sz1 && v1[i] < v2[j]) {
r[i + j] = v1[i];
i++;
} else {
r[i + j] = v2[j];
j++;
}
}
r[sz1 + sz2] = val[id];
return r;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> t;
while (t--) {
cin >> h >> g;
inc(i, 1, (1 << h) - 1) cin >> val[i];
inc(i, 1 << h - 1, (1 << h) - 1) sub[i] = vector<int>(1, val[i]);
dec(i, (1 << h - 1) - 1, 1) {
sub[i] = Merge(sub[i << 1], sub[i << 1 | 1], i);
}
set<int> s;
ll sum = 0;
inc(i, 1 << g - 1, (1 << g) - 1) {
nxt[i] = sub[i][0];
s.insert(nxt[i]);
sum += nxt[i];
}
dec(i, (1 << g - 1) - 1, 1) {
inc(j, 0, (int)sub[i].size() - 1) if (sub[i][j] > nxt[i << 1] &&
sub[i][j] > nxt[i << 1 | 1]) {
nxt[i] = sub[i][j];
s.insert(nxt[i]);
sum += nxt[i];
break;
}
}
cout << sum << "\n";
dec(i, (1 << h) - 1, 1) {
if (s.find(val[i]) == s.end()) cout << i << " ";
}
cout << "\n";
}
}
Codeforces 1329C - Drazil Likes Heap(堆+贪心)的更多相关文章
- CF R631 div2 1330 E Drazil Likes Heap
LINK:Drazil Likes Heap 那天打CF的时候 开场A读不懂题 B码了30min才过(当时我怀疑B我写的过于繁琐了. C比B简单多了 随便yy了一个构造发现是对的.D也超级简单 dp了 ...
- Codeforces 631 (Div. 2) E. Drazil Likes Heap 贪心
https://codeforces.com/contest/1330/problem/E 有一个高度为h的大顶堆:有2h -1个不同的正整数,下标从1到2h−1,1<i<2h, a[i] ...
- Codeforces Round #631 div1C(或者div2E) Drazil Likes Heap 题解
题目链接:https://codeforces.com/contest/1329/problem/C 或者:https://codeforces.com/contest/1330/problem/E ...
- #292 (div.2) D.Drazil and Tiles (贪心+bfs)
Description Drazil created a following problem about putting × tiles into an n × m grid: "The ...
- Heap堆的理解以及在IAR中如何设置堆的大小
文章首发于浩瀚先森博客 堆栈的概念在脑海里已经存在有一段时间了,今天就测试来整理下Heap堆.栈以后再说. 堆区不像全局变量和局部变量总是有指定的内存大小,它是为了在程序运行时动态分配内存而设定的一块 ...
- java - Stack栈和Heap堆的区别
首先分清楚Stack,Heap的中文翻译:Stack—栈,Heap—堆. 在中文里,Stack可以翻译为“堆栈”,所以我直接查找了计算机术语里面堆和栈开头的词语: 堆存储 ...
- Heap(堆)和stack(栈)有的区别是什么。
java的内存分为两类,一类是栈内存,一类是堆内存.栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这个 ...
- JAVA Stack栈和Heap堆的区别(转)
首先分清楚Stack,Heap的中文翻译:Stack—栈,Heap—堆. 在中文里,Stack可以翻译为“堆栈”,所以我直接查找了计算机术语里面堆和栈开头的词语: ...
- Codeforces 437C The Child and Toy(贪心)
题目连接:Codeforces 437C The Child and Toy 贪心,每条绳子都是须要割断的,那就先割断最大值相应的那部分周围的绳子. #include <iostream> ...
随机推荐
- Java框架之SpringBoot-Web构建-yml-模块-注解
SpringBoot Spring Boot是一站式整合所有应用框架的框架,简化Spring应用开发,约定大于配置,去繁从简,开箱即用,准生产环境的运行时应用监控框架 快速构建 SpringBoot ...
- Skeleton Screen加载占位图(内容出现前显示灰色占位图)的分析与实现
今天有几个好友问了这个叫加载占位图的实现方法,我还在此问题下做了个回答.由于国内对这个的名词是各有各的叫法,所以这里直接用加载占位图来解释.相信很多人都看到过图中这样的加载方式: 这个图是一个国内知名 ...
- 关于地址栏url的一些小结
1.获取整个地址栏地址 //获取整个地址栏地址 var href = window.location.href; console.log(href); 以上代码就是获取整个url地址 2.获取url协 ...
- 【前端】这可能是你看过最全的css居中解决方案了~
1.水平居中:行内元素解决方案 适用元素:文字,链接,及其其它inline或者inline-*类型元素(inline-block,inline-table,inline-flex) html部分代码: ...
- 关于在elasticSearch中使用聚合查询后只显示10个bucket的问题
先看下面es查询语句 { "size": 0, "aggs" : { "all_articleId" : { "terms&quo ...
- vue移动端字体大小设置
const setRemUnit = () => { const docEl = document.documentElement; // IPhone6下750像素来设计,实际像素375px, ...
- jwt的token如何使用
JWT简介: JWT(JSON WEB TOKEN):JSON网络令牌,JWT是一个轻便的安全跨平台传输格式,定义了一个紧凑的自包含的方式在不同实体之间安全传输信息(JSON格式).它是在Web环境下 ...
- view添加阴影
//@mg:masksToBounds必须为NO否者阴影没有效果 // cell.layer.masksToBounds = NO; cell.layer.contentsScale = [UI ...
- 探究Spring Boot中的接收参数问题与客户端发送请求传递数据
结合此篇参考Spring框架学习笔记(9)--API接口设计相关知识及具体编码实现 在使用Spring Boot进行接收参数的时候,发现了许多问题,之前一直都很忙,最近才稍微有空研究一下此问题. 网上 ...
- C 和 C++语言中的内存拷贝函数memcpy()
memcpy指的是C和C++使用的内存拷贝函数 函数原型为void *memcpy(void *destin, void *source, unsigned n): 函数的功能是从源内存地址的起始位置 ...