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;
}