题面:Luogu2168 UOJ#130
追逐影子的人,自己就是影子。 ——荷马
这题其实就是一个k叉Huffman树
所以我们用堆维护即可(像合并果子一样做就好了)
不过合并果子可以看作二叉Huffman,这里k叉
没关系,每次选k个合并就好了啊
但是如果(n-1)%(k-1)不等于0的话,那是不可能完全合并掉的
那也没关系,我们把少的用0补上,那就没有问题了
于是这么一道NOI的题就这么被攻下了
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#include <ctime>
#include <map>
#include <queue>
#include <cstdlib>
#include <string>
#include <climits>
#include <set>
#include <vector>
#define int long long
using namespace std;
struct ppap{int x,y;};
bool operator <(ppap a,ppap b){return a.x==b.x?a.y>b.y:a.x>b.x;}
priority_queue<ppap>q;
signed main()
{
int n,k;scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;i++){
int x;scanf("%lld",&x);
q.push((ppap){x,1});
}int sum=n;
if((sum-1)%(k-1)){
for(int i=sum+1;i<=sum+(k-1)-(sum-1)%(k-1);i++)q.push((ppap){0,1});
sum+=(k-1)-(sum-1)%(k-1);
}
int ans=0;
for(;sum>1;sum=sum-k+1){
int a=0,b=0;
for(int i=1;i<=k;i++){
a+=q.top().x;b=max(b,q.top().y);
q.pop();
}
ans+=a;q.push((ppap){a,b+1});
}
printf("%lld\n%lld",ans,q.top().y-1);
return 0;
}