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. date命令详解

    基础命令学习目录首页 原文链接:https://www.cnblogs.com/qmfsun/p/4598650.html date "+今天是%Y-%d-%m,现在是%H:%M:%S&qu ...

  2. 配置Tomcat使用HTTP/2

    转自: https://zhuanlan.zhihu.com/p/21349186 前情提要: Tomcat高效响应的秘密(一) Sendfile与Gzip Tomcat高效响应的秘密(二) keep ...

  3. “Hello World!”团队第六周第六次会议

    “Hello World!”团队第六周第六次会议   博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 八.checkout& ...

  4. 【欢迎来怼】 Beta发布事后诸葛亮会议

    队名:欢迎来怼 项目名称:博客园Android端APP 小组成员队长:田继平成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文 ————————————————————————————————————— ...

  5. Notes of Daily Scrum Meeting(11.14)

    Notes of Daily Scrum Meeting(11.14) 今天是项目第三周的周五,按原计划这时我们的项目应该已经要进入尾声进行组装调试了,但由于之前放假还有队员们的 效率比较低的原因,我 ...

  6. 2018-2019-20172329 《Java软件结构与数据结构》第七周学习总结

    2018-2019-20172329 <Java软件结构与数据结构>第七周学习总结 教材学习内容总结 <Java软件结构与数据结构>第十一章-二叉查找树 一.概述 1.什么是二 ...

  7. 【每日scrum】第一次冲刺day3

    学习安卓,和小伙伴讨论百度API调用的问题,最后决定自己写地图

  8. CS小分队第二阶段冲刺站立会议(6月4日)

    昨日成果:昨天一直在对主界面进行修改,遇到问题没有进展 遇到的问题:我代码写的不够缜密,各按钮信息添加的删除的时候总是有重名或者覆盖现象,需要有一次大的检查 今日计划:冲刺已经结束,项目的难度超过了预 ...

  9. 第二阶段每日站立会议Second Day

    昨天我在手机端安装cpp后进行界面效果测试以及进一步完善 今天对图片显示的大小进行调整 遇到的问题:当图片太小时,显示一块灰色区域,不美观

  10. NetFPGA-SUME下reference_nic测试

    Reference_nic Reference_nic是NetFPGA-SUME中提供的一个参考Demo,本文主要介绍如何构建并在SUME上运行reference_nic. GIT源 git clon ...