存在序列问题,其中对于每个索引 我们在数组中 i 定义了两个数量。
让 r
成为这样的最大索引
r>=i
以及 i
到 r
(包括在内)的子数组要么不减少或不增加。
让 l
成为 l<=i
以及来自 l
到 i (包括)是非减少或不增加。
现在,我们将索引 i
的点定义为等于
max(|Ai−Al|,|Ai−Ar|)
即可。
请注意,l
和r
可能因每个索引而异。
问题的任务是找到具有最大点的数组A
的索引。
我的逻辑:
首先扫描数组中的所有元素。
对于每个索引,找到l和r,它们遵循递增或递减的顺序,然后计算该索引的最大点。
我的问题是这需要花费O(N^2)
时间。
问题可以在更短的时间内完成吗?
答案 0 :(得分:0)
两个连续的相同数字具有相同的点,并且不会影响任何其他点的点,因此可以假设此方案不存在。
因此,考虑一个没有连续相同数字的输入数组a,可以假设子序列中最长的非减少或不增加是[I1
,I1
] [{{ 1}},I2
] ... [Ix
,n - 1
],由index表示,n是数组的长度。每个递减的子序列之后是增加的子序列,反之亦然。
对于任何Ii,索引为Ii的点的点等于max(|AIi - AI(i - 1)|, |AIi - AI(i + 1)|)
。 Ii
和I(i + 1)
之间的任何索引都必须小于Ii
和I(i + 1)
,并且不必考虑。
因此,我们只需要找出所有AIi
和AI(i + 1)
之间的最大值。
经过大量的尝试,我终于接受了我的程序(主要是因为两个int 32之间的差异不一定在signed int 32范围内),代码如下。
#include <stdio.h>
#define MAXN 200002
long long a[MAXN];
long long abs(long long n)
{
if (n >= 0)
return n;
return -n;
}
long long find_score(int size)
{
int i = 0;
long long maximum_score = 0;
while (i < size - 1)
{
//Jump over consecutive indentical numbers
while (a[i + 1] == a[i])
{
if (i < size - 1)
i++;
else
break;
}
int j = i + 1;
int inc_or_dec = a[j] > a[i];
while (j < size - 1 && (!((a[j + 1] > a[j]) ^ inc_or_dec) || a[j + 1] == a[j]))j++;
if (abs(a[j] - a[i]) > maximum_score)
maximum_score = abs(a[j] - a[i]);
i = j;
}
return maximum_score;
}
int main()
{
int n;
scanf("%d", &n);
while (n--)
{
int num;
scanf("%d", &num);
for (int i = 0; i < num; i++)
{
scanf("%lld", a + i);
}
printf("%lld\n", find_score(num));
}
while (1);
return 0;
}
很高兴知道我的代码中是否存在任何“实现定义”问题。