题目描述
难度分:1300
输入T(≤2×104)表示T组数据。所有数据的n之和≤105。
每组数据输入n(2≤n≤105)和一个1~n的排列p。
选一个p的长度至少为2的子序列b,最大化b的所有相邻元素的绝对差的和。
即S=|b1−b2|+|b2−b3|+…
在S最大的前提下,b的长度尽量小。输出任意一个符合要求的b。
注:子序列不一定连续。
输入样例
2
3
3 2 1
4
1 3 4 2
输出样例
2
3 1
3
1 4 2
算法
贪心构造
观察一下可以发现一个事实:当给你的是一个单调数组时,最划算的方式就是选首尾两个元素构成一个长度为2的子序列,这样和你选超过两个元素得到的S值是一样的。
有了这个结论问题就迎刃而解了,a[1]和a[n]是必须要选的,对于中间的i∈[2,n−1],只要满足a[i]是峰(a[i]>max(a[i−1],a[i+1]))或者谷(a[i]<min(a[i−1],a[i+1])),就选上。
复杂度分析
时间复杂度
仅遍历了一遍数组a就得到了答案,因此算法的时间复杂度为O(n)。
空间复杂度
出了原数组a,以及要返回的子序列seq(其实这个空间也是可以省掉的,在构造的过程中直接打印),仅使用了有限几个变量,因此额外空间复杂度为O(1)。
python代码
t = int(input())
for _ in range(t):
n = int(input())
a = list(map(int, input().split()))
seq = [a[0]]
for i in range(1, n - 1):
if a[i] > max(a[i - 1], a[i + 1]):
seq.append(a[i])
elif a[i] < min(a[i - 1], a[i + 1]):
seq.append(a[i])
seq.append(a[n - 1])
print(len(seq))
for num in seq:
print(num, end=' ')
print()