【CodeChef】Graph Cost(動態規劃)

Alric發表於2024-05-23

題目大意:

對於任意\(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;
}

相關文章