环路运输 (单调队列+环形处理)

题目描述

在一条环形公路旁均匀地分布着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
",ans);
    return 0;
}

对于单调队列,有一部分变量时需要枚举的,主要维护的就是那些不变的变量,也就是首尾标志维护的变量。我们只要更新好这些变量,枚举好此时变量,则就一定能维护好的最大值和最小值。

 
原文地址:https://www.cnblogs.com/ifmyt/p/13906480.html