题目描述
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