Running Miles

该文章介绍了一个算法问题,目标是找到数列中一个区间[l,r],使得区间的前三大值之和与(r-l)的差最大。解决方案包括计算前缀和与后缀和,以确定每个位置之前和之后的最大值,然后通过遍历找到最优解。
摘要由CSDN通过智能技术生成

题目:

 

题意解析: 

给定一个长度为 n 的数列 a,请找出其中的一个区间 [l,r],最大化区间内的前三大值之和与 r−l 的差,并求出这个值。

题解:

(1)求出前三大值之和,我们可以求出一个数,这个数之前的最大数,这个数之后的最大数。这样不就是前三大值之和。

(2)关于处理 r-l ,分解为b[left]-left,b[right]-right。解决 r-l 的问题。

(3)使用关于前缀数组,一个后缀数组,用前缀记录,在i个数之前最大的数,用后缀记录,在i个数之后最大的数。为什么要使用a[i]=max(a[i-1]-1,b[i]),a[i-1]-1是b[left]-left+1,同理后缀也是一样的,所以到ans=max(ans,a[i-1]+b[i]+c[i+1]-2);这里要-2

代码:

#include<bits/stdc++.h>
using namespace std;
int t,n,k;
long long int a[100009],c[100009],b[100009],ans;
int main() {
	cin>>t;
	while(t--) {
		cin>>n;
		ans=a[0]=c[n+1]=0;
		for(int i=1; i<=n; i++) {
			cin>>b[i];
			a[i]=c[i]=0;
		}
		// 前缀处理,求出前i个数中最大的数与i的距离
		for(int i=1; i<=n; i++) {
			a[i]=max(a[i-1]-1,b[i]);
		}
		// 后缀处理
		for(int i=n; i>=1; i--) {
			c[i]=max(c[i+1]-1,b[i]);
		}
		for(int i=2; i<n; i++) {
			ans=max(ans,a[i-1]+b[i]+c[i+1]-2);
		}
		cout<<ans<<endl;
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值