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. LeetCode 刷题笔记 2. 有效的括号(Valid Parentheses)

    tag: 栈(stack) 题目描述 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合. 左括号必须 ...

  2. [Github] Github使用教程

    前言 Github是一个面向开源及私有软件项目的托管平台.它可以免费使用,并且速度快速,拥有超多的用户.是目前管理软件开发和发现已有代码的首选平台.下面将向Github新手介绍相关操作. 正文 注册 ...

  3. [机器学习]-K近邻-最简单的入门实战例子

    本篇文章分为两个部分,前一部分主要简单介绍K近邻,后一部分是一个例子 第一部分--K近邻简介 从字面意思就可以容易看出,所谓的K近邻,就是找到某个样本距离(这里的距离可以是欧式距离,曼哈顿距离,切比雪 ...

  4. C++多态深入分析!

    以下分析是基于VS2010的.以后会使用G++分析看看G++如何处理多态! // polymorphic_test.cpp : 定义控制台应用程序的入口点. // /** 特别注意:实现C++多态,除 ...

  5. Mac SpotLight无法搜索

    在终端运行如下命令: sudo mdutil -i on /

  6. oracle和mysql对时间与字符串的转换

    1,oracle to_date(#{item.value},'YYYY-MM-DD hh24-mi-ss') to_char(CRERATE_TIME,'YYYY-MM-DD hh24-mi-ss' ...

  7. Hibernate的使用技巧②

    1.Hibernate统计记录的数量 Criteria c = session.createCriteria(User.class.getName());        c.setProjection ...

  8. SE Springer小组《Spring音乐播放器》可行性研究报告一、二

    1 引言 1.1编写目的 <软件工程>课程,我们团队计划开发一个音乐播放器.本文档是基于网络上现有的音乐播放器的特点,团队计划实现的音乐播放器功能和团队人员的综合实力等情况,说明该软件开发 ...

  9. Monty Hall 问题与贝叶斯定理的理解

     三门问题(Monty Hall problem),是一个源自博弈论的数学游戏问题,大致出自美国的电视游戏节目Let's Make a Deal.问题的名字来自该节目的主持人蒙提·霍尔(Monty H ...

  10. 批量梯度下降(BGD)、随机梯度下降(SGD)以及小批量梯度下降(MBGD)的理解

      梯度下降法作为机器学习中较常使用的优化算法,其有着三种不同的形式:批量梯度下降(Batch Gradient Descent).随机梯度下降(Stochastic Gradient Descent ...