《演算法競賽進階指南》0x55環形與後效處理DP 環路運輸
阿新 • • 發佈:2020-08-01
題目連結:https://www.acwing.com/problem/content/291/
題目給出的是一個環狀公路,公路上有n個點,每個點都有一個值w[i],點之間的距離就是從兩點沿著環的最短路徑,問最大的w[i]+w[j]+dis(i,j)是多少。
由於這個dis不會超過n/2,所以可以列舉一個點i,對[i-n/2,i-1]區間查詢w[i]-i的最大值。將環變成鏈狀處理即可,這裡由於一段區間計算的值只和端點有關,是一個滑動視窗求最值的問題,通過單調佇列可以在O(N)時間內求解。維護一個長度不超過len=n/2而且單調下降的序列的索引。
單調佇列中,假設k<j<i且維護的屬性值T[k]<T[j],那麼在不失更好的決策的情況下是不會保留k的,因為明顯j更大而且j更加靠近i。
程式碼:
#include<iostream> #include<cstdio> using namespace std; const int maxn = 2000010; int w[maxn]; int q[maxn]; int n; int main(){ cin>>n; for(int i=1;i<=n;i++){ scanf("%d",&w[i]); w[i+n]=w[i]; } int l=1,r=1; int len=n/2; int ans=-1;for(int i=1;i<=n*2;i++){ if(l<=r && q[l]<i-len)l++; ans=max(ans,w[i]+w[q[l]]+i-q[l]); while(l<=r && w[q[r]]-q[r]<=w[i]-i)r--; q[++r]=i; } cout<<ans<<endl; return 0; }