题目:
题意解析:
给定一个长度为 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;
}