B. Hills And Valleys(思维,模拟)
一道水题,但是没做出来,仔细想想是自己想的不全。
改一个数,让新的序列的谷和峰最少。遍历1到n的所有位置,将初始威胁记录下来,改变位于i的位置的大小。
改变大小的方法无非就是以下5种情况:
1.a[i]改成a[i - 1]和a[i + 1]中的最小值。
2.a[i]改成a[i - 1]和a[i + 1]中的最大值。
3.a[i]改成比a[i - 1]和a[i + 1]小。
4.a[i]改成比a[i - 1]和a[i + 1]大。
5.a[i]改成在a[i - 1]和a[i + 1]之间。
将改变之后的威胁记录下来,记录最小值。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 10;
#define int long long
int t, n, a[maxn];
int judge(int i) {
if (i >= 2 && i <= n - 1) {
if (a[i] > a[i + 1] && a[i] > a[i - 1]) return 1;
if (a[i] < a[i + 1] && a[i] < a[i - 1]) return 1;
}
return 0;
}
signed main() {
cin >> t;
while (t--) {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
int ans = 0, temp = 0;
for (int i = 2; i <= n - 1; i++)
if (judge(i)) ans++;
for (int i = 1; i <= n; i++) {
int now = judge(i - 1) + judge(i + 1) + judge(i), last = 1e9, f = a[i];
a[i] = min(a[i - 1], a[i + 1]) - 1; //比小的小
last = min(last, judge(i - 1) + judge(i + 1) + judge(i));
a[i] = max(a[i - 1], a[i + 1]) + 1; //比大的大
last = min(last, judge(i - 1) + judge(i + 1) + judge(i));
a[i] = min(a[i - 1], a[i + 1]) + 1; //位于中间
last = min(last, judge(i - 1) + judge(i + 1) + judge(i));
a[i] = a[i - 1]; //相等
last = min(last, judge(i - 1) + judge(i + 1) + judge(i));
a[i] = a[i + 1]; //相等
last = min(last, judge(i - 1) + judge(i + 1) + judge(i));
temp = max(temp, now - last);
a[i] = f;
}
cout << ans - temp << endl;
}
}