Luogu P2168 [NOI2015]荷马史诗
https://www.luogu.com.cn/problem/P2168
题面
给定一棵含\(n\)个叶子节点的\(k\)叉树,其中第\(i\)的叶子有点权\(a_i\),要求最小化\(\sum w_i\times l_i\)
其中\(l_i\)表示到根节点的距离
并求出在权值和最小的情况下树的最小深度
分析
huffman树
先将\(k\)叉树用权值为0的点补满,然后每次选出权值最小的\(k\)个点合并
可以用堆实现,但更能用队列实现
先将叶子节点排序,再对合并的点单独开一个队列
因为随着合并数的增加,点权大小是严格递增的
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+5;
int n,k,l,r; ll a[N],ans;
struct A{ll x; int y; }q[N];
int main() {
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) {
scanf("%lld",&a[i]);
}
while((n-1)%(k-1)) n++;
sort(a+1,a+n+1);
int L=1; l=1,r=0;
for(int i=n;i;i-=k-1) {
A t=(A){0,0};
for(int j=1;j<=k;j++) {
if(l>r||L<=n&&a[L]<=q[l].x) {
t.x+=a[L],L++;
} else {
t.x+=q[l].x,t.y=max(t.y,q[l].y),l++;
}
}
ans+=t.x,t.y++;
q[++r]=t;
if(i==k) {
printf("%lld\n%d\n",ans,t.y);
return 0;
}
}
}

浙公网安备 33010602011771号