B. Most socially-distanced subsequence
Question:
Give an array aaa , find a subsequencessin the arrays (length isxxx),满足“ ∑ i = 1 x ∣ s [ i ] − s [ i − 1 ] ∣ \sum_{i=1}^x|s[i]-s[i-1]| ∑i=1x∣s[i]−s[i−1 ] | . Maximum "If there is more than one answer liesxxx smaller subsequence
Idea:
We observe an increasing sequence s = {1, 2, 3, 4, 6} s = \{1, 2, 3, 4, 6\}s={
1,2,3,4,6},则:
∑ i = 1 x ∣ s [ i ] − s [ i − 1 ] ∣ = 5 \sum_{i=1}^x|s[i]-s[i-1]| = 5 ∑i=1x∣s[i]−s[i−1]∣=5,因为 s [ i ] > s [ i − 1 ] s[i] > s[i-1] s[i]>s[i−1 ] , so when we disassemble the formula, we find that onlys [5] − s [1] = 6 − 1 = 5 s[5]-s[1] = 6-1 = 5s[5]−s[1]=6−1=5. Similarly, when the sequence is decreasing, the same conclusion can be obtained. (Solved the shortest problem).
Sequence{x, z, y} \{x,z,y\}{
x,with ,y } , if on the number linezzz在 x , y x,y between x and y (such asz 1 z_1with1) ,∣ y - z ∣ + ∣ z - x ∣ = y - x | yz | + | zx | = yx∣y−z∣+∣z−x∣=and−x if it is likez 2 z_2with2In the same way, we can find ∣ y − z ∣ + ∣ z − x ∣ = z − y + z − x |yz|+|zx| = z-y+zx∣y−z∣+∣z−x∣=with−and+with−x , this finds∑ i = 1 x ∣ s [i] − s [i − 1] ∣ \sum_{i=1}^x|s[i]-s[i-1]|∑i=1x∣s[i]−s[i−1 ] | largest andxxThe methods used to minimize x are the same.
The rest is our simulation, to find out the continuous increasing or decreasing sequence in the array a, and remove the middle element without affecting the result.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
const int inf = 0x7ffffff;
const ll INF = 0x7fffffffffff;
ll f[][2] = {
1, 0, 0, 1, -1, 0, 0, -1}, n, m;
ll s[N];
int read() {
int x = 0; int f = 1; char s = getchar();
while(s < '0' || s > '9') {
if(s == '-') f = -1; s = getchar();}
while(s >= '0' && s <= '9') {
x = (x << 3) + (x << 1) + s - 48; s = getchar();}
return x * f;
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int t;
cin >> t;
while(t--) {
n = read();
m = n;
for(int i=1; i<=n; i++) s[i] = read();
if(n == 2) {
cout << 2 << endl;
for(int i=1; i<=n; i++) cout << s[i] << ' ';
cout << endl;
continue;
}
int i = 1, j = 2, k = 3;//从数组下标1,2,3开始扫描,每三个三个比较。
while(k <= n) {
//判断是否连续递增或
if(s[j]>s[i] && s[k]>s[j] || s[j]<s[i] && s[j]>s[k]) {
m--;
s[j] = -1;/做标记。
j++, k++;
}
else i = j, j++, k++;
}
cout << m << endl;
for(int i=1; i<=n; i++) {
if(s[i] != -1) cout << s[i] << ' ';
}
cout << endl;
}
return 0;
}