最优规则式 XDU1024

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

你可能感兴趣的:(扫描与信息维护)