题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2339
解题报告:题目太长了,比赛的时候根本看不懂,完了之后问了什么意思,发现好简单,就是输入n个数据,把这n个数据放入一个集合中,然后每次从集合中取出两个最小的数,求出他们的和,并且把这个和加入到结果当中 ,并且要把这个和放入到集合当中,然后再次从集合中取出两个数,就这样一直做,直到这个集合为空。其实就是用一个最小堆,然后每次从堆里面去粗两个数,求和再把这个和插入到堆中,也就是最裸的堆,要注意的是这题数据范围超出int了,要用long long 。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long INT; INT tree[];
int rear; void push(INT d)
{
tree[++rear] = d;
int p = rear;
while(p/ >= && tree[p] <= tree[p/])
{
swap(tree[p],tree[p/]);
p /= ;
}
} INT get_top()
{
INT d = tree[];
swap(tree[],tree[rear--]);
return d;
} void pop(int p)
{
int i = p , j = *p;
if(j > rear)
return ;
if(j + <= rear && tree[j + ] < tree[j])
j++;
if(tree[i] >= tree[j])
{
swap(tree[i],tree[j]);
pop(j);
}
else return;
} int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
INT sum = ,d = ,x = ;
rear = ;
for(int i = ;i < n;++i)
{
scanf("%lld",&d);
push(d);
}
for(int i = ;i<n;++i)
{
x = get_top();
pop();
x += get_top();
pop();
sum += x;
push(x);
}
printf("%lld\n",sum);
if(T) printf("\n");
}
return ;
}