http://www.lydsy.com/JudgeOnline/problem.php?id=1078 (题目链接)

题意

  给出一个斜堆,并给出其插入的操作,求一个字典序最小的插入顺序。

Solution

  YY了很久,画出样例,你会发现很神奇的性质:一般情况下,因为是一个一个插入节点的,左子树与右子树的大小要么相等要么左子树比右子树大1。

  然而,我忽略了一条链的情况,写写画画搞来搞去,最后分类讨论了一下。关键的地方是要想到我们对于一棵子树,在前提条件相同的情况下,应尽肯能的早插入根,因为是个小根堆,所以根的字典序一定是最小的。

  我们这样操作:对于节点x,它的左儿子l,右儿子r。dfs下去,分别得到l的子树的合并顺序和r的子树的合并顺序,再对x,l,r进行合并,跟归并排序有些类似吧。

  对于节点x:

  左子树大于右子树

  1.左-右>=2

  不停插左,直到左右子树大小相等

  插根,先插左再插右

  2.左-右=1

  插根,先插左再插右

  左子树等于右子树

  插根,先插右再插左

  左子树小于右子树

  1.右-左>=2

  不停插右,直到左-右=1

  插根,先插左再插右

  2.右-左=1

  先插右2个

  插根,先插左再插右

  然后一路dfs递归合并就可以了

细节

  节点标号从1开始会比较好

代码

// bzoj1078
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 1<<30
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=100;
struct heap {int l,r;}tr[maxn];
int size[maxn],n;
vector<int> v[maxn]; void dfs(int x) {
size[x]=1;
if (tr[x].l) dfs(tr[x].l);
if (tr[x].r) dfs(tr[x].r);
size[x]+=size[tr[x].l]+size[tr[x].r];
}
void merge(int x) {
int l=tr[x].l,r=tr[x].r;
if (l) merge(l);
if (r) merge(r);
int ll=0,rr=0;
if (size[l]>size[r]) {
if (size[l]-size[r]>=2) {
for (;size[l]-size[r];ll++,size[l]--) v[x].push_back(v[l][ll]);
v[x].push_back(x);
while (size[l] || size[r]) {
if (size[l]==size[r]) v[x].push_back(v[r][rr++]),size[r]--;
else v[x].push_back(v[l][ll++]),size[l]--;
}
}
else {
v[x].push_back(x);
while (size[l] || size[r]) {
if (size[l]==size[r]) v[x].push_back(v[r][rr++]),size[r]--;
else v[x].push_back(v[l][ll++]),size[l]--;
}
}
}
else if (size[l]==size[r]) {
v[x].push_back(x);
while (size[l] || size[r]) {
if (size[l]==size[r]) v[x].push_back(v[r][rr++]),size[r]--;
else v[x].push_back(v[l][ll++]),size[l]--;
}
}
else if (size[l]<size[r]) {
if (size[r]-size[l]>=2) {
for (;size[l]-size[r]<1;rr++,size[r]--) v[x].push_back(v[r][rr]);
v[x].push_back(x);
while (size[l] || size[r]) {
if (size[l]==size[r]) v[x].push_back(v[r][rr++]),size[r]--;
else v[x].push_back(v[l][ll++]),size[l]--;
}
}
else {
v[x].push_back(v[r][rr++]),size[r]--;
v[x].push_back(v[r][rr++]),size[r]--;
v[x].push_back(x);
while (size[l] || size[r]) {
if (size[l]==size[r]) v[x].push_back(v[r][rr++]),size[r]--;
else v[x].push_back(v[l][ll++]),size[l]--;
}
}
}
}
int main() {
scanf("%d",&n);
for (int x,i=1;i<=n;i++) {
scanf("%d",&x);
if (x<100) tr[x+1].l=i+1;
else tr[x-99].r=i+1;
}
dfs(1);
merge(1);
for (int i=0;i<v[1].size();i++) printf("%d ",v[1][i]-1);
return 0;
}

【bzoj1078】 SCOI2008—斜堆的更多相关文章

  1. BZOJ1078 [SCOI2008]斜堆 堆

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1078 题意概括 斜堆(skew heap)是一种常用的数据结构.它也是二叉树,且满足与二叉堆相同的 ...

  2. [bzoj1078][SCOI2008][斜堆] (贪心)

    Description 斜堆(skew heap)是一种常用的数据结构.它也是二叉树,且满足与二叉堆相同的堆性质:每个非根结点的值都比它父亲大.因此在整棵斜堆中,根的值最小.但斜堆不必是平衡的,每个结 ...

  3. BZOJ1078: [SCOI2008]斜堆

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1078 每一次进入的点一定是一个极左节点,然后将它所处在的整棵树左右翻转.加上一些情况的处理. ...

  4. 【BZOJ1078】[SCOI2008]斜堆(性质题)

    [BZOJ1078][SCOI2008]斜堆(性质题) 题面 BZOJ 洛谷 题解 考虑一下这道题目的性质吧.思考一下最后插入进来的数是什么样子的.首先因为它是最后插入进来的,所以一定是比某个数小,然 ...

  5. 【bzoj1078】[SCOI2008]斜堆

    2016-05-31 16:34:09 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1078 挖掘斜堆的性质233 http://www.cp ...

  6. BZOJ 1078: [SCOI2008]斜堆

    1078: [SCOI2008]斜堆 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 770  Solved: 422[Submit][Status][ ...

  7. 【BZOJ 1078】 1078: [SCOI2008]斜堆

    1078: [SCOI2008]斜堆 Description 斜堆(skew heap)是一种常用的数据结构.它也是二叉树,且满足与二叉堆相同的堆性质:每个非根结点的值都比它父亲大.因此在整棵斜堆中, ...

  8. [SCOI2008]斜堆

    题目大意 1.题目描述 斜堆(skew heap)是一种常用的数据结构. 它也是二叉树,且满足与二叉堆相同的堆性质: 每个非根结点的值都比它父亲大.因此在整棵斜堆中,根的值最小. . 但斜堆不必是平衡 ...

  9. P2475 [SCOI2008]斜堆(递归模拟)

    思路 可并堆真是一种神奇的东西 不得不说这道题是道好题,虽然并不需要可并堆,但是能加深对可并堆的理解 首先考虑斜堆的性质,斜堆和左偏树相似,有如下的性质 一个节点如果有右子树,就一定有左子树 最后插入 ...

随机推荐

  1. python虚拟环境管理之virtualenv,virtualenvwrapper,pipenv,conda

    虚拟环境的作用 使python环境拥有独立的包,避免污染原本的python环境.为不同的项目创建不同的环境可以避免安装的库过于庞大和相互干扰. 例如你想在同一台机器上开发用python2和python ...

  2. L2 Helios OPcodez

    天堂2 Helios太阳神版本 的客户端和服务端封包 *********************** Client ***********************00 SendLogOut01 Req ...

  3. 用 Delphi 7 实现基于 FFMS2 的视频转 GIF 工具 [原创]

    儿子经常要把自拍的视频(ts格式)转成表情包,下载了几个工具都不大好用,更多的还要收费.那就想自己写一个吧,没想到这一下断断续续地,居然 3 个月过去了.现在总算弄出个作品来了,结个贴吧.唉,天资愚钝 ...

  4. Netty源码分析第4章(pipeline)---->第2节: handler的添加

    Netty源码分析第四章: pipeline 第二节: Handler的添加 添加handler, 我们以用户代码为例进行剖析: .childHandler(new ChannelInitialize ...

  5. XSS跨站脚本

    1.反射型 非持久化,需要用户自己点击才可以触发 通常出现在搜索框 <?php $id=$_GET['id']; echo $id; ?> http://127.0.0.1/test/sc ...

  6. 备份win10的驱动程序

    目录 折腾历程 怎么备份驱动 备份的驱动如何使用 关于驱动程序的OS兼容性 驱动程序的其他安装方式 1.折腾历程 从闲鱼上收了一个INSIGNIA的二合一笔记本,w7100,因原装win10性能不行自 ...

  7. 数据库之python操作mysql

    目录 一.pymysql 二.SQLAchemy 2.操作使用 (1)连接数据库 (2)执行原生SQL语句 (3)ORM操作-数据表操作 (4)ORM操作-数据行操作 (5)更多例子 一.pymysq ...

  8. 如何使用g++编译调用dll的c++代码

    本文将有以下4个部分来讲如何使用g++编译调用dll的c++代码. 1.如何调用dll 2.动态链接和静态链接的区别 3.g++的编译参数以及如何编译调用dll的c++代码 4.总结 1.如何调用dl ...

  9. mysql/mybatis之合并两个表的查询结果

    下面这段sql是把两个表中各自符合条件的count值相加,返回结果是两个之和 SELECT sum(result) FROM ( SELECT COUNT(*) result FROM TEST_A ...

  10. Scrum Meeting 2 -2014.11.2

    今天大家读完代码后又聚在了一块讨论了许多.确定了重点的任务和分工细节.提出了许多问题和改进的方案.还有讨论分析了关于团队作业 - 软件分析和用户需求调查,初步决定目标软件为必应的输入法和词典,团队为争 ...