• 偷懒的桐桐


    偷懒的桐桐

    题目描述

    桐桐的老师布置桐桐写一个小根堆,但是桐桐不会堆的操作,所以想了一个偷懒的办法:
    堆是一棵完全二叉树,每个结点有一个权。小根堆的根的权最小,且根的两个子树也是一个堆。可以用一个数组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,且各不相同。

    分析:构造字典序最大的二叉树;

       预处理排序,第一个肯定是根;

       接下来根据贪心原则,剩下的分成2半,第二半的第一个既是根的第一个儿子,第一半的第一个既是根的第二个儿子;

       每一半继续递归即可;

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <list>
    #include <bitset>
    #define rep(i,m,n) for(i=m;i<=n;i++)
    #define rsp(it,s) for(set<int>::iterator it=s.begin();it!=s.end();it++)
    #define vi vector<int>
    #define pii pair<int,int>
    #define mod 1000000007
    #define inf 0x3f3f3f3f
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define pi acos(-1.0)
    const int maxn=1e6+10;
    const int dis[4][2]={{0,1},{-1,0},{0,-1},{1,0}};
    using namespace std;
    ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;}
    int n,m,a[maxn],ans[maxn];
    void dfs(int now,int l,int r)
    {
        ans[now]=a[l];
        if(l==r)return;
        int len=(r-l)/2;
        dfs(now*2+1,l+len+1,l+2*len);
        dfs(now*2+2,l+1,l+len);
    }
    int main()
    {
        int i,j,k,t;
        scanf("%d",&n);
        rep(i,0,n-1)scanf("%d",&a[i]);
        sort(a,a+n);
        dfs(0,0,n-1);
        printf("%d",ans[0]);
        rep(i,1,n-1)printf(" %d",ans[i]);
        printf("
    ");
        //system ("pause");
        return 0;
    }
  • 相关阅读:
    head命令
    less命令
    解决get方法传递URL参数中文乱码问题
    The method convert(String) of type DateConverter must override a superclass method
    Tomcat Can't load AMD 64-bit .dll on a IA 32
    聚合函数查询 group by having
    string[] 清理重复+反转显示
    C# GetValueList 获得字符串中开始和结束字符串中间得值列表
    C# GetValue 正则获取开始结束代码
    string [] 去除重复字符两个方法
  • 原文地址:https://www.cnblogs.com/dyzll/p/5743059.html
Copyright © 2020-2023  润新知