题目大意

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. ubuntu中gdb调试工具的使用

    首先有一段.c代码 1.可调试gcc编译:gcc -g -o xxx xxx.c 2.启动gdb调试 gdb xxx 3.在main函数处设置断点 break main 4.运行程序 run 5.其他 ...

  2. netty学习资源收集

    Netty学习笔记 Netty In Actions CSDN专栏 一起学Netty-CSDN专栏 Netty In Action中文版

  3. java thread 线程锁同步,锁,通信

    12.线程同步 当多个线程访问同一个数据时,非常容易出现线程安全问题.这时候就需要用线程同步 Case:银行取钱问题,有以下步骤: A.用户输入账户.密码,系统判断是否登录成功 B.用户输入取款金额 ...

  4. 获取目录-Winform

    // 获取程序的基目录. System.AppDomain.CurrentDomain.BaseDirectory // 获取模块的完整路径. System.Diagnostics.Process.G ...

  5. Activiti获取ProcessEngine的三种方法

    1.通过ProcessEngineConfiguration获取 package cn.lonecloud.mavenActivi; import org.activiti.engine.Proces ...

  6. 机器学习之支持向量机(二):SMO算法

    注:关于支持向量机系列文章是借鉴大神的神作,加以自己的理解写成的:若对原作者有损请告知,我会及时处理.转载请标明来源. 序: 我在支持向量机系列中主要讲支持向量机的公式推导,第一部分讲到推出拉格朗日对 ...

  7. hdu3016 线段树+简单DP

    以每个方块左右坐标区间为节点建立字典树,每个节点保存这个区间对应的方块的下标,将方块按照高度排序. 如何得到第i个方块可以移动到的两个方块呢?将所有方块排完序,将前i-1个方块放入字典树,根据第i个方 ...

  8. mybatis与spring的整合(使用接口实现crud)

    本人刚刚接触mybatis,今天把它和spring整合起来用了一个上午==. 一开始是通过配置文件来配置,后来尝试用了一下注解,觉得mybatis的注解真的有点恶心...一大坨的,所以我还是建议使用配 ...

  9. Python接口测试,Requests模块讲解:GET、POST、Cookies、Session等

    文章最下方有对应课程的视频链接哦^_^ 一.安装.GET,公共方法 二.POST 三.Cookies 四.Session 五.认证 六.超时配置.代理.事件钩子 七.错误异常

  10. C语言老司机学Python (五)

    今天看的是标准库概览. 操作系统接口: 用os模块实现. 针对文件和目录管理,还有个shutil模块可以用. 例句: import os os.getcwd() # 返回当前的工作目录 os.chdi ...