1.题目描述:点击打开链接
2.解题思路:本题要求找到四个数,满足a<b<c<d,且arr[a]+arr[d]-arr[b]-arr[c]最大。可以利用扫描法来解决。首先可以将目标式理解为两个不相交区间上的最大差值的和。那么目标就是找所有这些不想交区间最大差值的和的最大值。定义Left[i]数组维护区间[0,i)上的最大差值,Right[i]维护区间[i,n)上的最大差值。那么这两个数组不难找到如下递推式:
Left[i]=max{Left[i-1],arr[i-1]-minx};
上式中,minx是区间[0,i-1)上的最小元素。同理可得Right数组的递推式:
Right[i]=max{Right[i+1],maxx-arr[i]};
上式的maxx表示区间[i+1,n)上的最大元素。每次都可以只用O(N)的时间即可算出数组的所有值。这样,最终的答案就是max(Left[i]+Right[i])。总的时间复杂度为O(N)。
3.代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;
#define N 100000+5
int a[N];
int Left[N], Right[N];
typedef long long ll;
int main()
{
//freopen("t.txt", "r", stdin);
int T;
scanf("%d", &T);
while (T--)
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
int ans = 0;
memset(Left, 0, sizeof(Left));
memset(Right, 0, sizeof(Right));
Left[2] = a[1] - a[0];
int minx = min(a[0],a[1]);
for (int i = 3; i <= n; i++)
{
Left[i] = max(Left[i - 1], a[i - 1] - minx);
minx = min(minx, a[i - 1]);//minx晚于Left[i]更新
}
Right[n - 2] = a[n - 1] - a[n - 2];
int maxx = max(a[n - 1], a[n - 2]);
for (int i = n - 3; i >= 0; i--)
{
Right[i] = max(Right[i + 1], maxx - a[i]);
maxx = max(maxx, a[i]);
}
for (int i = 2; i < n - 1; i++)
ans = max(ans, Left[i] + Right[i]);
printf("%d\n", ans);
}
return 0;
}