题目链接

题意

给出一个高度为 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(堆+贪心)的更多相关文章

  1. CF R631 div2 1330 E Drazil Likes Heap

    LINK:Drazil Likes Heap 那天打CF的时候 开场A读不懂题 B码了30min才过(当时我怀疑B我写的过于繁琐了. C比B简单多了 随便yy了一个构造发现是对的.D也超级简单 dp了 ...

  2. 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] ...

  3. Codeforces Round #631 div1C(或者div2E) Drazil Likes Heap 题解

    题目链接:https://codeforces.com/contest/1329/problem/C 或者:https://codeforces.com/contest/1330/problem/E ...

  4. #292 (div.2) D.Drazil and Tiles (贪心+bfs)

    Description Drazil created a following problem about putting  ×  tiles into an n × m grid: "The ...

  5. Heap堆的理解以及在IAR中如何设置堆的大小

    文章首发于浩瀚先森博客 堆栈的概念在脑海里已经存在有一段时间了,今天就测试来整理下Heap堆.栈以后再说. 堆区不像全局变量和局部变量总是有指定的内存大小,它是为了在程序运行时动态分配内存而设定的一块 ...

  6. java - Stack栈和Heap堆的区别

    首先分清楚Stack,Heap的中文翻译:Stack—栈,Heap—堆.         在中文里,Stack可以翻译为“堆栈”,所以我直接查找了计算机术语里面堆和栈开头的词语:        堆存储 ...

  7. Heap(堆)和stack(栈)有的区别是什么。

    java的内存分为两类,一类是栈内存,一类是堆内存.栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这个 ...

  8. JAVA Stack栈和Heap堆的区别(转)

          首先分清楚Stack,Heap的中文翻译:Stack—栈,Heap—堆.         在中文里,Stack可以翻译为“堆栈”,所以我直接查找了计算机术语里面堆和栈开头的词语:      ...

  9. Codeforces 437C The Child and Toy(贪心)

    题目连接:Codeforces 437C  The Child and Toy 贪心,每条绳子都是须要割断的,那就先割断最大值相应的那部分周围的绳子. #include <iostream> ...

随机推荐

  1. electron+vue制作桌面应用--自定义标题栏

    electron会默认显示边框和标题栏,如下图 我们来看一下如何自定义一个更加有(gao)意(da)思(shang)的标题栏,例如网易云音乐这种 首先我们要把默认的标题栏删掉,找到主进程中创建窗体部分 ...

  2. 从输入URL到页面展示

    当我们输入 URL 并按回车后,浏览器会对 URL 进行检查,首先判断URL格式,比如是ftp http ed2k等等,我们这里假设这个URL是http://hellocassie.cn,那么浏览器会 ...

  3. 前端每日实战:60# 视频演示如何用纯 CSS 创作一块乐高积木

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/qKKqrv 可交互视频 此视频是可 ...

  4. 「ReStory」在 Markdown 中自由书写 React 组件 (Beta)

    介绍 先睹为快 我们在开发一个小小的 React 组件库,但是我们遇到了一个大难题,那就是为我们的组件库书写一个合理的文档. 作为组件文档,我们非常希望我们的组件用例代码能够展现出来,是的我们在书写文 ...

  5. 解决IOS下window.open页面打不开问题

    问题如标题所写,在ajax回调里面拿到即将要跳转的链接url,使用window.open(linkUrl),没有起作用,而且代码也没有报错,查找原因是:大部分现代的浏览器(Chome/Firefox/ ...

  6. bug的前世今生

    项目上发现的产品bug,若本地有问题,那就是漏测 1.提到产品bug系统 2.需要追踪,要么是漏测,要么是改出来的问题,漏测的需要补充到测试点里 项目上发现的产品bug,若本地没问题,那就是项目上的产 ...

  7. Java多线程并发01——线程的创建与终止,你会几种方式

    本文开始将开始介绍 Java 多线程与并发相关的知识,多谢各位一直以来的关注与支持.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程的创建方式 在 Java 中,用户常用的主动创建 ...

  8. scrapy启动

    创建项目 在开始爬取之前,您必须创建一个新的Scrapy项目. 进入您打算存储代码的目录中,运行下列命令: scrapy startproject scrapytest 第一种scrapy gensp ...

  9. MVC项目中存储公用链接方法

    小白成长记第一篇,随手记录一下小常识 将固定地址写在web.config文件appSettings中 Controller调用方法:

  10. React hooks详解

    此篇文章仅是对hooks入门的总结,老鸟略过吧~ React从16.8.X以后增加了一个新特性,react hooks 让我们看看这个新特性又带来了哪些惊喜呢~以下内容我们采取不同方式创建组件来进行对 ...