传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1345
首先最后剩下的一定是原序列中最大的
于是我们定义solve(l,r)表示合并l到r的最小代价
那么很显然最后合并区间的最大值更优,而且最后合并的代价一定是最大值
于是solve(l,r)=solve(l,p-1)+a[p]+solve(p+1,r)+a[p],显然这个递归是线性的(windows下会爆栈,linux不会……)
我们需要快速寻找到区间最大值,那就ST表呗
听说还有单调栈做法,太神了不会……
Code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
typedef long long LL;
int a[maxn],n;
LL ans=0;
int getint(){
int res=0;char c=getchar();
while(!isdigit(c))c=getchar();
while(isdigit(c))res=(res<<3)+(res<<1)+c-'0',c=getchar();
return res;
}
int f[20][maxn],g[20][maxn];
void init(){
int BIT=0;
for(int i=n;i;i>>=1,BIT++);
for(int i=1;i<=n;i++)f[0][i]=a[i],g[0][i]=i;
for(int i=1;i<=BIT;i++)
for(int j=1;j<=n-(1<<i)+1;j++){
if(f[i-1][j]>f[i-1][j+(1<<i-1)])
f[i][j]=f[i-1][j],g[i][j]=g[i-1][j];
else f[i][j]=f[i-1][j+(1<<i-1)],g[i][j]=g[i-1][j+(1<<i-1)];
}
}
int Qmax(int l,int r){
int BIT=0;
for(int i=r-l+1;i;i>>=1,BIT++);BIT--;
if(f[BIT][l]>f[BIT][r-(1<<BIT)+1])return g[BIT][l];
else return g[BIT][r-(1<<BIT)+1];
}
LL solve(int l,int r){
if(l==r)return 0;
if(l+1==r)return max(a[l],a[r]);
int p=Qmax(l,r);
LL ans=0;
if(l<=p-1)ans+=solve(l,p-1)+a[p];
if(r>=p+1)ans+=solve(p+1,r)+a[p];
return ans;
}
int main(){
n=getint();
for(int i=1;i<=n;i++)a[i]=getint();
init();
cout<<solve(1,n)<<endl;
return 0;
}