思路+二分

来源:互联网 发布:lumia800软件下载 编辑:程序博客网 时间:2024/04/30 08:36

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


0 0