oldssoj2680F(哈夫曼树)

题目描述

MZL is a mysterious mathematician, and he proposed a mysterious function at his young age.

Stilwell is very confused about this function, and he need your help.
First of all, given n positive integers Ai and Ai≥Ai+1.
Then, generate n positive integers Bi

Define f(i,j) for i,j∈Z

Find f(n,1).

输入

The first line of the input contains a single number T, the number of test cases.

For each test case, the first line contains a positive integer n, and the next line contains n positive integers Ai.
T≤100, 1≤n≤105, ∑n≤106, 1≤Ai≤104.

输出

For each test case, output f(n,1) in a line.

样例输入

331 1 1528 26 25 24 110996 901 413 331 259 241 226 209 139 49

样例输出

523311037

提示

case 1 :


f(1,1)=0

f(1,2)=f(1,1)+3=3

f(1,3)=f(1,2)+3=6

f(2,1)=min(f(2,1)+2,f(1,2))=3

f(2,2)=min(f(2,1)+2,f(1,3))=5

f(2,3)=f(2,2)+2=7

f(3,1)=min(f(3,1)+1,f(2,2))=5

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#define ll long long
using namespace std;
ll n,ans;
priority_queue<ll,vector<ll>,greater<ll> >q;
inline ll get(){
    char c;while(!isdigit(c=getchar()));
    ll v=c-48;while(isdigit(c=getchar()))v=v*10+c-48;
    return v;
}
int main(){
    int t=get();
    while(t--){
        while(!q.empty())q.pop();
        n=get();ans=0;
        for(int i=1;i<=n;++i){
            ll x=get();q.push(x);
        }
        while(q.size()>1){
            ll a=q.top();q.pop();
            ll b=q.top();q.pop();
            ans+=b+a;
            q.push(a+b);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

思想:好题!

           f[ i ] [ j ]为当前共有j个空叶节点,决策ai的位置。有两个状态可以转移:1、直接放——f[ i+1 ][ j-1 ]    2、跳一层,叶子节点分叉,到下一层再决策——f[ i ][ 2*j ],此决策需要ai+……an的代价(即Bi);一个哈夫曼模型;从f[ 1 ][ 1 ]到f[ n ][ 1 ];

           此模型倒过来便和本题所给的函数相符。即树的路径就是结果。Orz

           从小到大排序,用堆维护,用priority_queue


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值