您的位置:首页 > 其它

合并果子----(堆的应用)

2016-08-29 21:53 113 查看
合并果子人人皆知,然而这并不是DP,是可以每次选最小的就可以对,

but我直接暴力,神奇的TLE了!

于是乎,我用了堆



#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;
int d[100000];    //堆
int main()
{
int m,n,i,j,k,l;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>d[i];
k=i;
while(k>1 && d[k]<d[k/2])  //如果d[i]小于左子树,则往上浮
{
swap(d[k],d[k/2]); //上浮过程
k=k/2;
}
}
int len=n,ans=0;
while(len>1)
{
int s=0,u;
s+=d[1]; //取出最小值合并
d[1]=d[len--]; //填充堆顶
u=1;
while(len>=u*2 && d[u]>d[u*2] ||len>=u*2+1 && d[u]>d[u*2+1]) //如果d[u]大于左子树,则像下沉,即调整堆
{
int t=u*2;   //下沉过程
if(d[u*2]>d[u*2+1]) t++;
swap(d[u],d[t]);
u=t;
}
s+=d[1]; //再取一次最小值
d[1]=d[len--];
//d[len+1]=0;
u=1;
while(len>=u*2 && d[u]>d[u*2] ||len>=u*2+1 && d[u]>d[u*2+1])
{
int t=u*2;
if(d[u*2]>d[u*2+1]) t++;
swap(d[u],d[t]);
u=t;
}
ans+=s; //合并果子后又放入堆中,最后剩下的即是解....
d[++len]=s;
u=len;
while(u>1 && d[u]<d[u/2])
{
swap(d[u],d[u/2]);
u=u/2;
}
}
cout<<ans; //解
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: