思路+二分

http://exam.upc.edu.cn/problem.php?id=1550

题意:给一堆数字,生成最小堆,要求是输出的数组是字典序最大的(不用构造堆)

思路:最小堆的特点是根节点的值最小,其他随意。为保证字典序最大,我们让左子树全部都比右子树大。只需对数组排序再二分来找。二分是需要 注意是如何分配区间的。用int mid = l + (r - l) / 2;//r - l表示的是一个元素存入ans数组中,剩下的待分的数量。另左子树比右子树大,固左子树是右区间,右子树是左区间。因为数组是从0开始的,因此左子树是i * 2 + 1,右子树是 i* 2 + 2

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <sstream>
#include <string>
#include <algorithm>
#include <list>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdlib>
using namespace std;
int a[65540];
int ans[65540];
int n;

void dfs(int now,int l,int r)//注意是左闭右闭区间
{

    if(l > n-1)
        return;
    ans[now] = a[l];
    if(l >=  r)
        return ;
    int mid = l + (r - l) / 2;//r - l表示的是一个存入ans数组中,剩下的待分的数量
    dfs(now * 2 + 1 ,mid + 1,r);//左子树大,右子树小
    dfs(now * 2 + 2,l + 1,mid);


}
int main()
{
//freopen("in.txt","r",stdin);

	scanf("%d",&n);
	for(int i = 0; i < n; i ++)
    {
        scanf("%d",&a[i]);
    }
    sort(a ,a + n);
        dfs(0,0,n -1);
    for(int i = 0; i < n - 1; i ++)
    {
        printf("%d ",ans[i]);
    }
    printf("%d\n",ans[n - 1]);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值