环路运输 (单调队列+环形处理)
题目描述
在一条环形公路旁均匀地分布着N座仓库,编号为1~N,编号为 i 的仓库与编号为 j 的仓库之间的距离定义为 dist(i,j)=min(|i-j|,N-|i-j|),也就是逆时针或顺时针从 i 到 j 中较近的一种。每座仓库都存有货物,其中编号为 i 的仓库库存量为 Ai。在 i 和 j 两座仓库之间运送货物需要的代价为 Ai+Aj+dist(i,j)。求在哪两座仓库之间运送货物需要的代价最大。1≤N≤10^6,1<=Ai<=10^7。
输入
第一行一个整数N,第二行N个整数A1~AN。
输出
一个整数,表示最大代价。
样例输入 Copy
5
1 8 6 2 5
样例输出 Copy
15
解法:对于此题,先进行环形处理,然后在做最大值处理,用单调队列维护。
#include<cstdio> #include<algorithm> using namespace std; const int N=2e6+10; int a[N],n,q[N],ans; int main() { scanf("%d",&n); for(int i=1; i<=n; i++) scanf("%d",&a[i]),a[n+i]=a[i]; int hd=1,tl=1; q[1]=1; for(int i=2; i<=2*n; i++) { while(hd<=tl&&i-q[hd]>n/2)hd++; ans=max(ans,a[i]+a[q[hd]]+i-q[hd]); while(hd<tl&&a[i]-i>=a[q[tl]]-q[tl])tl--; q[++tl]=i; } printf("%d\n",ans); return 0; }
对于单调队列,有一部分变量时需要枚举的,主要维护的就是那些不变的变量,也就是首尾标志维护的变量。我们只要更新好这些变量,枚举好此时变量,则就一定能维护好的最大值和最小值。