众所周知的,小明家里有好多猫,经过一次“猫口普查”,我们得到了以下信息:

小明家里有 nn 只猫,第 ii 只猫的体重是 a_iai。然而小明热爱虐猫(并不),他决定对这些猫做一些有♂趣的事情

经过了两年半的练习之后,这些猫已经能完全听懂小明的指令了。

小明的指令分成两个阶段,具体步骤如下:

  1. 指定一种颜色,所有这种颜色的猫都会从猫窝里跑出来,此时小明需要付出总共为这些猫的体重的代价。例如,现在小明有三只红色的猫,体重分别为 {1,2,3}1,2,3,还有两只蓝色的猫,体重分别为 {7,8}7,8。此时如果小明声明的颜色是红色,那么所有红色的猫会出来,小明需要支付的代价为 66。如果小明声明的颜色是蓝色,那么所有蓝色的猫会出来,小明需要支付的代价为 1515。
  2. 对于现在出来的这些猫,小明选择其中的一部分,将他们染成一种新的颜色。然后放回所有的猫。

初始时所有猫都是白色。现在小明想知道,如果想要使得这些猫两两颜色都不同,最少需要花费多少代价。

题解:我们讲整体二分,然后依次分到最后我们会形成一颗树,树的叶子就是所有的猫,那么我们呢倒着从叶子结点看,这题就变成了每次选两只猫合并最后成一个猫的最终的最小代价,然后就变成了裸的哈夫曼树。

AC代码:

#include <iostream>
#include <cstring>
#include <string>
#include <map>
#include <queue>
#include <vector>
#include <cstdio>
#include <algorithm>
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int maxn=1e6+5;
main(){
int n;
cin>>n;
priority_queue<int,vector<int>,greater<int> >q;
for(int i=1;i<=n;i++){
int x;
cin>>x;
q.push(x);
}
int ans=0;
for(int i=1;i<n;i++){
int a=q.top();
q.pop();
int b=q.top();
q.pop();
ans+=a+b;
q.push(a+b);
}
cout<<ans<<endl;
}