題目大意:
對於任意\(1\le i,j\le n\),點\(i\)和\(j\)之間存在一條長度為\(\left| j-i\right|\cdot \max(A_i,A_j)\)的邊,求\(1\)到\(n\)的最短路。
\(1\)到\(n\)的最短路中經過的點的編號一定是單調遞增的,所以將此過程看作在陣列中從\(A_1\)經過\(A_2\),\(A_3\),……,\(A_{n-1}\)到達\(A_n\)的過程。
對於任意\(1\le i< n\),我們考慮從\(A_i\)到\(A_{i+1}\)的路上對答案的貢獻。要使答案最小,我們需要選出滿足\(1\le j\le i\)的\(j\)和滿足\(i+1\le k\le n\)的\(k\),使得\(\max(A_j,A_k)\)最小,這個最小值即為\(\max(pre_i,suf_{i+1})\)。因此,題目的答案為\(\sum_{i=1}^{n-1}\max(pre_i,suf_{i+1})\)。
上式中的\(pre_i=\min([A_1,A_2,...,A_i])\),\(suf_i=\min([A_i,A_{i+1},...,A_n])\),這兩個序列可以透過遞推求出。
#include<bits/stdc++.h>
#define pt printf(">>>")
#define mid (((l)+(r))/2)
using namespace std;
typedef long long ll;
const ll N=1e6+10,inf=1e18+10,mod=1e9+7;
ll n,a[N],pre[N],suf[N];
int main(){
int T=1;
cin >> T;
while(T--){
ll ans=0;
cin >> n;
for(ll i=1;i<=n;i++)cin >> a[i];
pre[1]=a[1],suf[n]=a[n];
for(ll i=2;i<=n;i++)pre[i]=min(pre[i-1],a[i]);
for(ll i=n-1;i;i--)suf[i]=min(suf[i+1],a[i]);
for(ll i=1;i<=n-1;i++)ans+=max(pre[i],suf[i+1]);
cout << ans << endl;
}
return 0;
}