AcWing 289. 环路运输,《算法竞赛进阶指南》,单调队列优化dp,滑动窗口求最大值,环形与后效性处理

289. 环路运输 - AcWing题库

在一条环形公路旁均匀地分布着 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)。

求在哪两座仓库之间运送货物需要的代价最大。

输入格式

第一行包含一个整数 N。

第二行包含 N 个整数 A1∼AN。

输出格式

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

数据范围

2≤N≤106,

1≤Ai≤107

输入样例:
复制代码
5
1 8 6 2 5
输出样例:
复制代码
15

解析:单调队列,动规

如果使用暴力的方法我们可以使用两个循环,一个枚举i,另一个枚举j

仔细观察这道题,我们可以发现一下性质
dist(i,j)=min(|i−j|,N−|i−j|)在 | i - j |<n/2 情况下,dist(i,j)=i-j;同时代价 Ai+Aj+dist(i,j) 可以转化成 Ai+i+Aj-j。

所以我们只需要枚举 i ,然后求出 i 右边 len=n/2 的范围内的最大的 Aj-j 即可

到这里可以看出来这可以单调队列来解决

cpp 复制代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
const int N = 2e6 + 5;
int n, m;
int w[N], q[N];

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &w[i]);
		w[i + n] = w[i];
	}
	int hh = 0, tt = -1;
	int len = n / 2;
	int ret = 0;
	for (int i = 1; i <= 2 * n; i++) {
		if (hh <= tt && i - q[hh] > len)hh++;
		ret = max(ret, w[i] + w[q[hh]] + i - q[hh]);
		while (hh <= tt &&w[q[tt]]- q[tt] <= w[i] - i)tt--;//这一步让队列从左往右变得单调,且左边的值最大
		q[++tt] = i;
	}
	printf("%d\n", ret);
	return 0;
}
相关推荐
仙俊红44 分钟前
LeetCode487周赛T2,删除子数组后的最终元素
数据结构·算法
-dzk-7 小时前
【代码随想录】LC 59.螺旋矩阵 II
c++·线性代数·算法·矩阵·模拟
风筝在晴天搁浅7 小时前
hot100 78.子集
java·算法
Jasmine_llq7 小时前
《P4587 [FJOI2016] 神秘数》
算法·倍增思想·稀疏表(st 表)·前缀和数组(解决静态区间和查询·st表核心实现高效预处理和查询·预处理优化(提前计算所需信息·快速io提升大规模数据读写效率
超级大只老咪7 小时前
快速进制转换
笔记·算法
m0_706653238 小时前
C++编译期数组操作
开发语言·c++·算法
故事和你918 小时前
sdut-Java面向对象-06 继承和多态、抽象类和接口(函数题:10-18题)
java·开发语言·算法·面向对象·基础语法·继承和多态·抽象类和接口
qq_423233908 小时前
C++与Python混合编程实战
开发语言·c++·算法
TracyCoder1238 小时前
LeetCode Hot100(19/100)——206. 反转链表
算法·leetcode
m0_715575348 小时前
分布式任务调度系统
开发语言·c++·算法