模拟 poj 2166 Heapsort

来源:互联网 发布:sentinel 1 数据下载 编辑:程序博客网 时间:2024/06/08 16:38

题目链接:

http://poj.org/problem?id=2166

题目大意:

求一个最大堆,使得经过堆排序的过程,交换的次数最多。

解题思路:

这个题昨天晚上想了会,没想出来,今早一起来就想出来喽。

分析:要想使得堆排序交换的次数最多,可以这样构造---每次让1都交换到最后。再分析易知,可以通过递推来得出当前的树结构。

假设现在一共有n个节点,显然save[1]=n,save[n]=1,当堆顶去掉后,1移到了堆顶,要想让1移到第n-1号位置,可以借助当节点为n-1时树的结构,只用在n-1的情况,沿堆顶到最后一个元素的路径统一右旋一个位置(及儿子等于父亲,依次更新到堆顶)。然后把n放到堆顶,1放到n号位置。这样理解后,从前往后递推构造树结构,就可以得出答案。

代码:

//#include<CSpreadSheet.h>#include<iostream>#include<cmath>#include<cstdio>#include<sstream>#include<cstdlib>#include<string>#include<string.h>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#include<ctime>#include<bitset>#define eps 1e-6#define INF 0x3f3f3f3f#define PI acos(-1.0)#define ll __int64#define LL long long#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1#define M 1000000007#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define Maxn 550000int save[Maxn];int main(){   //freopen("in.txt","r",stdin);   //freopen("out.txt","w",stdout);   int n;   while(~scanf("%d",&n))   {       save[1]=1;       for(int i=2;i<=n;i++)       {           int cur=i-1;           while(cur>=1) //从n-1的情况递推出n的情况           {               save[cur]=save[cur/2]; //右旋 相当于儿子等于父亲               cur/=2; //向上直到叶子节点           }           save[1]=i; //再把第一个元素置为当前最大           save[i]=1; //最后一个元素置为1       }       printf("%d",save[1]);       for(int i=2;i<=n;i++)            printf(" %d",save[i]);       putchar('\n');   }   return 0;}


0 0
原创粉丝点击