Luogu P2168 [NOI2015]荷馬史詩
阿新 • • 發佈:2020-11-27
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; } } }