【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;
}
posted @ 2024-05-23 13:51  Alric  阅读(6)  评论(0编辑  收藏  举报