偷懒的桐桐(递归)

偷懒的桐桐

时间限制: 1 Sec  内存限制: 64 MB
提交: 26  解决: 9
[提交][状态][讨论版]

题目描述

桐桐的老师布置桐桐写一个小根堆,但是桐桐不会堆的操作,所以想了一个偷懒的办法:
堆 是一棵完全二叉树,每个结点有一个权。小根堆的根的权最小,且根的两个子树也是一个堆。可以用一个数组a来记录一棵完全二叉树,a[1]为根结点,若结点 a[j]不是根结点,那么它的父亲为a[j div 2];若结点a[k]不是叶子结点,那么它的左儿子为a[2k],它的右儿子为a[2k+1]。
  桐桐希望一组数据按一定顺序依次插入数组中(即第i个数为a[i]),最后得出来就已经是一个堆,即不需要任何交换操作,若有多种方法,输出字典序最大的一组,使得这个数据更乱。
  

输入

输入的第1行为一个正整数n,为插入的数字的个数;
第2行包含n个正整数,为所有需要插入的数字,数字之间用空格隔开。
  为了简化题目,数据保证n=2k-1,即保证最后的堆是一棵满二叉树。
 

输出

输出包括1行,为插入的序列,数字之间用空格隔开,行末换行并没有空格。

样例输入

3
10 2 1

样例输出

1 10 2

提示

样例说明 1 2 10 与1 10 2都是满足要求的插入序列,但是1 10 2的字典序更大。

20%的数据:n≤7;
30%的数据:n≤15;
50%的数据:n≤1023;
100%的数:n≤65535,所有数字不超过108,且各不相同。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <time.h>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define inf 0x3f3f3f3f
#define mod 1000000007
typedef long long ll;
using namespace std;
const int N = 100000;
const int MAX = 2000;
int n,m,maxn=-1,cnt=0;
int a[N],s[N];
void dfs(int l,int r,int num) {
    int mid=(l+r)/2+1;
    s[num*2]=a[mid];
    s[num*2+1]=a[l+1];
    cnt+=2;
    if(mid<r) {
        dfs(mid,r,num*2);
        dfs(l+1,mid-1,num*2+1);
    }
     if(cnt>=n) {
        printf("%d",s[1]);
        for(int i=2; i<=cnt; i++) {
            printf(" %d",s[i]);
        }
        printf("
");
        exit(0);
    }
}
int main() {
    cin>>n;
    for(int i=0; i<n; i++) {
        cin>>a[i];
    }
    if(n==1){
        cout<<a[0]<<endl;
        exit(0);
    }
    sort(a,a+n);
    s[1]=a[0];cnt++;
    dfs(0,n-1,1);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/jianrenfang/p/5743852.html