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; }