CH 5501 环路运输 环拆链复制一倍+单调队列优化

版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/88942140

title

CH 5501
描述

在一条环形公路旁均匀地分布着N座仓库,编号为1~N,编号为 i 的仓库与编号为 j 的仓库之间的距离定义为 d i s t ( i , j ) = m i n ( i j , N i j ) dist(i,j)=min⁡(|i-j|,N-|i-j|) ,也就是逆时针或顺时针从 i 到 j 中较近的一种。每座仓库都存有货物,其中编号为 i 的仓库库存量为 A i A_i 。在 i 和 j 两座仓库之间运送货物需要的代价为 A i + A j + d i s t ( i , j ) A_i+A_j+dist(i,j) 。求在哪两座仓库之间运送货物需要的代价最大。 1 N 1 0 6 1 < = A i < = 1 0 7 1≤N≤10^6,1<=Ai<=10^7

输入格式

第一行一个整数N,第二行N个整数 A 1   A N A_{1}~A_{N}

输出格式

一个整数,表示最大代价。

样例输入

5
1 8 6 2 5

样例输出

15

analysis

这道题可以发现是一个环,那么把环断成链,复制一份。同时可以发现如果 i j i,j 是最优解,那么 j i n ÷ 2 ( j > i ) j−i≤n÷2(j>i) ,所以可以用单调队列解决问题。时间复杂度 O ( n ) O(n)

code

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
template<typename T>inline void read(T &x)
{
	x=0;
	T f=1, ch=getchar();
	while (!isdigit(ch) && ch^'-') ch=getchar();
	if (ch=='-') f=-1, ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
	x*=f;
}
int a[maxn<<1];
deque<int>q;
int main()
{
	int n;read(n);
	for (int i=1; i<=n; ++i)
		read(a[i]),a[i+n]=a[i];
	int ans=0;
	for (int i=1; i<=(n<<1); ++i)
	{
		while (q.size() && i-q.front()>(n>>1)) q.pop_front();
		if (q.size()) ans=max(ans,a[i]+a[q.front()]+i-q.front());
		while (q.size() && a[i]-i>a[q.back()]-q.back()) q.pop_back();
		q.push_back(i);
	}
	printf("%d\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/88942140