题目大意

1.题目描述

斜堆(skew heap)是一种常用的数据结构。
它也是二叉树,且满足与二叉堆相同的堆性质:
每个非根结点的值都比它父亲大。因此在整棵斜堆中,根的值最小。
.
但斜堆不必是平衡的,每个结点的左右儿子的大小关系也没有任何规定。
在本题中,斜堆中各个元素的值均不相同。
.
在斜堆\(H\)中插入新元素\(X\) 的过程是递归进行的:
(1)当\(H\)为空或者\(X\)小于\(H\)的根结点时,
\(X\)变为新的树根,而原来的树根(如果有的话)变为\(X\)的左儿子。
.
(2)当\(X\) 大于\(H\) 的根结点时,
\(H\)根结点的两棵子树交换,而\(X\)(递归)插入到交换后的左子树中。
.
给出一棵斜堆,包含值为\(0\)到\(n\)的结点各一次。
求一个结点序列,使得该斜堆可以通过在空树中依次插入这些结点得到。
如果答案不惟一,输出字典序最小的解。输入保证有解。
.
数据范围\(n \leq 50\)

2.样例文件:

input1:
6
100 0 2 102 4 104
output1:
4 6 5 2 0 1 3
..............................................................
input2:
7
0 100 1 102 2 3 5
output2:
2 5 0 3 4 6 7 1

思路及解法:

本题的数据范围出到\(n \leq 5 \times 10^3\)是肯定没问题的。
所以总结一下,本题时间复杂度\(O(n^2)\),空间复杂度\(O(n)\),思维复杂度\(O(n!)\)....
.
言归正传,这题到底怎么做?
由于每次都是插入左子树中,所以就会有一些神奇的事情。
我们考虑 最后一个插入的点 会有什么性质:
(1)性质1:它是一个极左节点(从根到它的路径都是走左子树)
(2)性质2:它一定没有右子树
显然满足上述条件的点有很多,那么仔细观察后可以发现:
性质3:对于树上任意一个点,如果它没有左子树,则它一定没有右子树
.
然后就可以搞一波事情了。
我们假设最后加入的点为 \(X\) ,如果它的祖先中存在点 \(Y\) 也满足性质\(1,2\),则:
<1>
若\(X\)不为叶子节点:
由于\(X\)插入\(Y\)的子树中时会反转\(Y\)的左右儿子,
那么\(Y\)的当前左子树中包含\(X\),而现在\(Y\)又没有右子树,
所以在插入前,\(Y\)只有右子树,没有左子树。
这显然与性质3矛盾,即这种情况不可能发生。
所以最后插入的点一定是 深度最浅的满足性质1,2的节点,设它为 \(del1\)。
<2>
若\(X\)为叶子节点:
那么即插入\(X\)前\(Y\)没有儿子。
所以这种情况显然是合法的,
即如果\(del1\)有左儿子\(del2\),且\(del2\)为叶子节点,那么\(del2\)也是合法的。
.
综上所述,最后插入的点可能为:
(1)深度最浅的满足性质1,2的节点
(2)深度最浅的满足性质1,2的节点的左儿子,前提是这个左儿子为叶子节点。
由于我们要保证字典序,所以存在(2)情况时我们则优先选叶子节点。
所以我们依照这个原则不断删点、修改。
最后把答案数组倒着输出即可(P.s :建议把所有点的编号都加\(1\)再处理)。

实现代码:

#include<bits/stdc++.h>
#define RG register
#define IL inline
#define mx 60
#define ll long long
using namespace std;

int n,root,fa[60],ls[60],rs[60],ans[60];

IL void Work(){
    for(RG int sq = 1; sq <= n; sq ++){
        RG int del1 = 0 , del2 = 0, x = root;
        while(x){ if(!rs[x]){del1 = x; break;} x = ls[x]; }
        if(!rs[ls[x]] && !ls[ls[x]] && ls[x])
            del2 = ls[x];
        if(del2){ans[sq] = del2; ls[del1] = 0; }
        else {
            ans[sq] = del1;
            ls[fa[del1]] = ls[del1]; fa[ls[del1]] = fa[del1];
        }
        if(!del2 && del1 == root)root = ls[del1] , fa[root] = 0;;
        RG int ff = fa[(del2)?del2 : del1];
        while(ff)
            swap(ls[ff],rs[ff]) , ff = fa[ff];
    }return;
}

int main(){
    cin >> n; n++; root = 1;
    for(RG int i = 2,f; i <= n; i ++){
        cin >> f;
        if(f >= 100){f-=100; f++; rs[f] = i; fa[i] = f;}
        else f++ , ls[f] = i , fa[i] = f;
    }
    Work();
    for(RG int i = n; i >= 1; i --)ans[i] --;
    for(RG int i = n; i >= 1; i --)cout<<ans[i]<<" ";
    return 0;
}

[SCOI2008]斜堆的更多相关文章

  1. BZOJ 1078: [SCOI2008]斜堆

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

  2. 【bzoj1078】[SCOI2008]斜堆

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

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

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

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

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

  5. BZOJ1078 [SCOI2008]斜堆 堆

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

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

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

  7. 【bzoj1078】 SCOI2008—斜堆

    http://www.lydsy.com/JudgeOnline/problem.php?id=1078 (题目链接) 题意 给出一个斜堆,并给出其插入的操作,求一个字典序最小的插入顺序. Solut ...

  8. P2475 [SCOI2008]斜堆

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

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

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

随机推荐

  1. 通过WMI获取机器信息

    PerformanceCounter的介绍就不多说了,MSDN上介绍的很详细: https://msdn.microsoft.com/zh-cn/library/system.diagnostics. ...

  2. php 处理并发问题

    对于商品抢购等并发场景下,可能会出现超卖的现象,这时就需要解决并发所带来的这些问题了 在PHP语言中并没有原生的提供并发的解决方案,因此就需要借助其他方式来实现并发控制. 方案一:使用文件锁排它锁 f ...

  3. docker dead but pid file exists

    CentOS 6安装docker 报docker dead but pid file exists 执行 yum install epel-release yum install docker-io ...

  4. Sublime 远程连接 Linux服务器

    Sublime是一款强大的编辑器,它的强大体现在它强大的插件. 要实现Sublime 远程连接 Linux服务器,需要使用插件SFTP. 一. 插件安装 用Package Control安装插件按下C ...

  5. ssh快速登录远程服务器

    以前我的做法是创建一个shell脚本运行,今天了解了可以按照下面的方式: vi .ssh/config ,写入如下内容 HOST api User abc Port HostName 123.123. ...

  6. LNMP搭建02 -- 编译安装Nginx

    [编译安装Nginx]   为了顺利安装Nginx,先安装下面这些: [CentOS 编译 nginx 前要做的事情] yum install gcc gcc-c++ kernel-devel yum ...

  7. Window Server 布署 WCF 服务 , 权限配置问题

    起因: 客户服务器运行环境要求提高安全性,建议数据连接串采取 加密措施 ,或改用 Window 验证 连接数据库服务 .于是我们打算选择后着,将后台服务(Window Server)数据库连接串调整为 ...

  8. C# winform中Show()和ShowDialog()的区别

    项目实际开发中需要根据不同的应用场景利用Show和ShowDialog,尤其是三级弹窗,慎用ShowDialog,否则会导致关闭第三级窗体时,自动关闭第二级,解决方案就是在第一级窗体弹出时采用Show ...

  9. 3.2 while 循环

    Python 编程中 while 语句用于循环执行程序,即在条件满足的情况下,循环执行某段代码.所以就需要在循环的代码块中设计一种使代码块循环执行一定次数后是while语句的条件不满足,从而中止whi ...

  10. PAT乙级 1034

    思路:是个水题,但是有坑.不能被题目忽悠了,题目保证正确的输出中没有超过整型范围的整数. 它只是保证结果不超出int,但是我们在运算过程中的乘法可能会超出int,直接把所有int改成long long ...