https://www.luogu.com.cn/problem/P5569
我们从序列中找到第一个
a
[
i
]
a[i]
a[i],使得
啊
a
[
i
−
1
]
≤
a
[
i
+
1
]
啊a[i-1] \le a[i+1]
啊a[i−1]≤a[i+1],然后将
a
[
i
−
1
]
a[i-1]
a[i−1]和
a
[
i
]
a[i]
a[i]合并,然后我们再从序列的第iii位向前找到第一个
a
[
k
]
a[k]
a[k]使得
a
[
k
]
>
a
[
i
−
1
]
+
a
[
i
]
a[k]>a[i−1]+a[i]
a[k]>a[i−1]+a[i],然后将这个数放在第
k
k
k个位置后。如果根本找不到这样的数就将这个合并的数扔在序列最前面就行了。如果连
i
i
i都找不到,显然最后两个数最小,直接将这两个数合并即可。
如以上操作直到最后只剩两堆石子为止,可以证明此时为最优解。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=41000;
ll n,a[N],ans,now=1,pro;
int main()
{
scanf("%lld",&n);
for(ll i=1;i<=n;i++) scanf("%lld",&a[i]);
while(now<n-1)
{
for(pro=now;pro<n-1;pro++)
{
if(a[pro+2]<a[pro]) continue;
a[pro+1]+=a[pro];
ans+=a[pro+1];ll k;
for(k=pro;k>now;k--) a[k]=a[k-1];
now++; k=pro+1;
while(now<k&&a[k-1]<a[k]) {a[k]^=a[k-1]^=a[k]^=a[k-1];k--;}
break;
}
if(pro==n-1) {a[n-1]+=a[n];ans+=a[n-1];n--;}
}
if(now==n-1) ans+=(a[n-1]+a[n]);
printf("%lld\n",ans);
return 0;
}