P10957 环路运输 题解

题目传送门

前置知识

单调队列/单调栈优化

解法

在仓库 \(1\)\(n\) 之间把环断开,然后复制一倍接在末尾,形成长度为 \(2n\) 的直线公路,即有 \(a_{i}=a_{i+n} (1 \le i \le n)\)

对于原来环形公路上的任意两座仓库 \(i,j(1 \le j<i \le n)\),代价为 \(\begin{cases} a_{i}+a_{j}+i-j & i-j \le \frac{n}{2} \\ a_{j+n}+a_{i}+j+n-i & i-j> \frac{n}{2} \end{cases}\)。即对于直线公路上的任意两座仓库 \(i,j(1 \le j<i \le 2n,i-j \le \frac{n}{2})\),代价为 \(a_{i}+a_{j}+i-j\)

单调队列维护递增的 \(a_{i}-i\) 即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
int a[2000010];
deque<int>q;
int main()
{
	int n,ans=0,i;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		cin>>a[i];
		a[i+n]=a[i];
	}
	for(i=1;i<=2*n;i++)
	{
		while(q.empty()==0&&i-q.front()>n/2)
		{
			q.pop_front();
		}
		if(q.empty()==0)
		{
			ans=max(ans,a[i]+a[q.front()]+i-q.front());
		}
		while(q.empty()==0&&a[q.back()]-q.back()<=a[i]-i)
		{
			q.pop_back();
		}
		q.push_back(i);
	}
	cout<<ans<<endl;
	return 0;
}
posted @ 2024-08-24 21:09  hzoi_Shadow  阅读(8)  评论(0编辑  收藏  举报
扩大
缩小