jozj4010-我才不是萝莉控呢【哈夫曼树】
生活随笔
收集整理的這篇文章主要介紹了
jozj4010-我才不是萝莉控呢【哈夫曼树】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目大意
從(n,1)(n,1)(n,1)到(1,1)(1,1)(1,1),一個數組AAA,滿足Ai≥Ai+1A_i\geq A_i+1Ai?≥Ai?+1
每次有兩個選擇走到(x?1,y+1)(x-1,y+1)(x?1,y+1),或(x,?y/2?)(x,\lfloor y/2\rfloor)(x,?y/2?)。后者需要消耗∑i=xnAi\sum_{i=x}^nA_i∑i=xn?Ai?的代價
求最小代價
解題思路
先預處理好Bx=∑i=xnAiB_x=\sum_{i=x}^nA_iBx?=∑i=xn?Ai?
很容易推出動態轉移方程
fi,j=min{fi?1,j+1,fi,j?2+Bi}f_{i,j}=min\{f_{i-1,j+1},f_{i,j*2}+B_i\}fi,j?=min{fi?1,j+1?,fi,j?2?+Bi?}
然后我們發現首先AiA_iAi?是有序的,而BiB_iBi?的性質
設fi,jf_{i,j}fi,j?表示放入了前iii個葉子節點,有jjj個空位的哈夫曼樹權值。
然后每次可以加入一個葉子節點在該層,且以后合并代價增加AiA_iAi?
也可以將兩個合并到新一層,空位多一些。
然后就愉快的發現這個的動態轉移和之前的一樣,其實就是哈夫曼樹。
然后每次肯定是優先選擇權值最小的合并,就是合并果子原題。
codecodecode
#include<cstdio> #define ll long long using namespace std; ll a[100010],num,x,n; long long s,u; void up(ll x) {ll t;while (x>1 && a[x]<a[x/2]){t=a[x];a[x]=a[x/2];a[x/2]=t;x/=2;} } void down(ll x) {ll t,y;while (x*2<=num && a[x]>a[x*2] || x*2+1<=num && a[x]>a[x*2+1]){y=x*2;if (x*2+1<=num && a[x*2]>a[x*2+1]) y++;t=a[x];a[x]=a[y];a[y]=t;x=y;} } void insert(ll x) {a[++num]=x;up(num);} int main() {int t;scanf("%lld",&t);while(t--){s=0;scanf("%lld",&n);num=0;for (ll i=1;i<=n;i++){scanf("%lld",&x);insert(x);} while (num>1){u=a[1];a[1]=a[num];num--;down(1);u+=a[1];a[1]=a[num];num--;down(1);s+=u;num++;a[num]=u;up(num);}printf("%lld\n",s);} }總結
以上是生活随笔為你收集整理的jozj4010-我才不是萝莉控呢【哈夫曼树】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 无线路由器怎么限制手机连接台数限制手机连
- 下一篇: 路由器怎么安装设置使用怎么配置无线路由器