CF1364B-B. Most socially-distanced subsequence
题意
给出一个长度为n的数字序列,让你找出它的一个子序列,长度为k,使得这个子序列的\(\vert s_1-s_2 \vert + \vert s_2-s_3 \vert +...+ \vert s_{k-1}-s_k\vert\)的值最大且k最小。
思路
首先肯定是将全部的数字都算上去这个,这个值会是最大的。但是题目要求k的值最小,所以要将这些数字中对于这个值的增大没有贡献的数字去掉。
那么什么样的数字对于这个值的增大没有贡献呢?假如一个有三个数字1、5、9,那么这个5对于这个值的增大就没有贡献,因为\(\vert 1-5 \vert + \vert 5 - 9\vert=\vert1-9\vert\);同样的,若三个数字是\(9、5、1\),这里面的5对于数字的增大也没有贡献。
综上,我们就是要把所有的比左边大比右边小的数字和比左边小比右边大的数字去掉,最终得到的序列就是答案。
AC代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
std::vector<int>a;
void solve() {
int n, t;
a.clear();
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &t);
a.push_back(t);
}
for (int i = 1; i < a.size() - 1; i++) {
if (a[i] > a[i - 1] && a[i] < a[i + 1]) {
a.erase(a.begin() + i);
i--;
} else if (a[i] < a[i - 1] && a[i] > a[i + 1]) {
a.erase(a.begin() + i);
i--;
}
}
printf("%d\n", (int)a.size());
for (int i = 0; i < a.size(); i++) {
printf("%d%c", a[i], " \n"[i == a.size() - 1]);
}
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}