【CodeChef】Graph Cost(动态规划)
题目大意:
对于任意\(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;
}