CH 5501 :环路运输(DP 环化处理)

本文介绍了一种解决环形数组中寻找两点的最大距离和的方法。通过将环形数组展开复制并使用单调队列来优化计算过程,最终实现O(n)的时间复杂度。文章包含完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:有一个圈上有n个点,编号从 1 ~ n,每个点有一个权值A[i],定义dist(i,j)=min(∣j−i∣,n−∣j−i∣)dist(i,j) = min(|j - i|,n - |j - i|)dist(i,j)=min(ji,nji),问两个点的A[i]+A[j]+dist(i,j)A[i] +A[j] + dist(i,j)A[i]+A[j]+dist(i,j)最大是多少。

题解:先将环断开复制一遍接在原序列的后面,由dist(i,j)dist(i,j)dist(i,j)的定义,当j−i>n2j - i > \frac{n}{2}ji>2n(这里假设j > i),实际上相当于 j,i+nj,i + nj,i+n 两个点。枚举每一个iii点作为起点,找出i+1,i+n2i + 1,i + \frac{n}{2}i+1,i+2n内的点使得A[i]+A[j]+(j−i)A[i] + A[j] + (j - i)A[i]+A[j]+(ji)最大,对于枚举的点,A[i]A[i]A[i]iii 已知,只需要维护 范围内最大的 A[j]+jA[j] + jA[j]+j 即可,相当于在一个长度为n2\frac{n}{2}2n的滑块内求最大值,用单调队列使复杂度均摊至O(n)

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
const int maxn = 1e6 + 10;
int h[2 * maxn],n;
int q[2 * maxn],top,rear,ans[2 * maxn],t[2 * maxn];
int main() {
	scanf("%d",&n);
	for(int i = 1; i <= n; i++) {
		scanf("%d",&h[i]);
		h[i + n] = h[i];
	}
	int len = n / 2,res = -0x3f3f3f3f;
	for(int i = 1; i <= 2 * n; i++) {
		while(top > rear && q[top] <= h[i] + i) top--;
		q[++top] = h[i] + i;t[top] = i;
		while(rear < top && t[rear + 1] <= i - len) rear++;
		if(i > len) {
			ans[i - len] = h[i - len] + q[rear + 1] - (i - len);
			res = max(res,ans[i - len]);
		}
	}
	printf("%d\n",res);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值