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. iOS静态库.a总结(2017.1.24增加脚本打包方法)

    修改于:2017.1.24 1.什么是库? 库是程序代码的集合,是共享程序代码的一种方式 2.根据源代码的公开情况,库可以分为2种类型 a.开源库 公开源代码,能看到具体实现 ,比如SDWebImag ...

  2. #1490 : Tree Restoration-(微软2017在线笔试)

    输入n m km个数,表示每层的节点个数接下来m行是每层的节点,节点顺序是从左往右的k个叶子节点k*k个矩阵,表示叶子节点之间的距离 输出:每个节点的父亲节点编号,root节点是0 题解:1.很明显, ...

  3. sqlplus远程连接oracle

    格式: sqlplus 用户名/密码@192.168.19.189:1521/MYTEST MYTEST 数据库名称

  4. java实验2实验报告(20135232王玥)

    实验二 Java面向对象程序设计 一.实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉S.O.L.I.D原则 5. 了解 ...

  5. <<梦断代码>>读后感

    <梦断代码>中对软件工程所面临的种种困难与艰难的描述,即便再过5年读也许都不过时.因为正如原作者所说,书中描写的是一队人马并肩扛起代码大石,虽历经磨难仍欲将其推上山顶的故事,而正是这种故事 ...

  6. 校友聊NABCD需求分析

    校友聊 NABCD需求分析 N:内网用户流量不够使用 A:基于局域网进行通讯 B:通讯不花费外网流量 C:目前学校还没有使用 D:将软件放在校园网,可以下载使用

  7. Gradle入门(6):创建Web应用项目

    如果要用 Java 和 Gradle 创建一个 Web 应用项目,我们首先需要创建一个 Java 项目,下面来看看该如何去做. 创建Java项目 我们可以使用Java插件创建一个Java项目,通过添加 ...

  8. Java 单生产者消费者问题

    package com.cwcec.test; class Resource { private int count = 0; private boolean flag = false; public ...

  9. grunt入门讲解4:如何创建task(任务)

    每当运行Grunt时, 你可以为其指定一个或多个任务, 这些任务用于告诉Grunt你想要它做什么事情. 如果你没有指定一个任务,并且你已经定义一个名为 "default" 的任务, ...

  10. Docker的volume机制实现容器数据的持久性存储

    1:可以启动一个容器的时候,临时指定挂载的volume,这个volume会自动创建,无需在宿主机上事先创建 docker run -it -v /busybox busybox:latest 登入到b ...