【ybtoj 高效进阶 4.1】 【二叉堆】 合并果子
题目
解题思路
将一个元素放进二叉堆(小根堆)
tree[++t]=x; //放入
int son=t;
while (son>1)
{
int fa=son/2;
if (tree[son]>=tree[fa]) //是否符合子节点大于父节点
return;
swap(tree[son],tree[fa]); //交换
son=fa; //继续维护
}
取出堆顶元素
int x=tree[1];
tree[1]=tree[t--]; //用最后一个替代堆顶
int fa=1;
while (fa*2<=t)
{
int son=fa*2;
if (son+1<=t&&tree[son]>tree[son+1]) son++; //求出较小的子节点
if (tree[son]>tree[fa]) break;
swap(tree[son],tree[fa]);
fa=son;
}
return x;
每次取出两个堆顶元素相加
再将和放入
代码
#include<iostream>
#include<cstdio>
using namespace std;
int t,n,x,sum,tree[10050];
void put(int x)
{
tree[++t]=x;
int son=t;
while (son>1)
{
int fa=son/2;
if (tree[son]>=tree[fa])
return;
swap(tree[son],tree[fa]);
son=fa;
}
}
int get()
{
int x=tree[1];
tree[1]=tree[t--];
int fa=1;
while (fa*2<=t)
{
int son=fa*2;
if (son+1<=t&&tree[son]>tree[son+1]) son++;
if (tree[son]>tree[fa]) break;
swap(tree[son],tree[fa]);
fa=son;
}
return x;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&x);
put(x);
}
for (int i=1;i<n;i++)
{
int l=get(),r=get();
sum+=l+r;
put(l+r);
}
printf("%d",sum);
}
用c++只带的
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
priority_queue<int> q; //默认大根堆
int n,x,y,ans;
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&x);
q.push(-x);
}
for (int i=1;i<n;i++)
{
x=q.top(),q.pop();
y=q.top(),q.pop();
ans-=x+y;
q.push(x+y);
}
printf("%d",ans);
return 0;
}