Hills And Valleys

You are given a sequence of n integers a1, a2, …, an. Let us call an index j (2≤j≤n−1) a hill if aj>aj+1 and aj>aj−1; and let us call it a valley if aj<aj+1 and aj<aj−1.

Let us define the intimidation value of a sequence as the sum of the number of hills and the number of valleys in the sequence. You can change exactly one integer in the sequence to any number that you want, or let the sequence remain unchanged. What is the minimum intimidation value that you can achieve?

Input
The first line of the input contains a single integer t (1≤t≤10000) — the number of test cases. The description of the test cases follows.

The first line of each test case contains a single integer n (1≤n≤3⋅105).

The second line of each test case contains n space-separated integers a1, a2, …, an (1≤ai≤109).

It is guaranteed that the sum of n over all test cases does not exceed 3⋅105.

Output
For each test case, print a single integer — the minimum intimidation value that you can achieve.

Example
inputCopy
4
3
1 5 3
5
2 2 2 2 2
6
1 6 2 5 2 10
5
1 6 2 5 1
outputCopy
0
0
1
0
Note
In the first test case, changing a2 to 2 results in no hills and no valleys.

In the second test case, the best answer is just to leave the array as it is.

In the third test case, changing a3 to 6 results in only one valley (at the index 5).

In the fourth test case, changing a3 to 6 results in no hills and no valleys.

官方题解:
更改ai的值只影响元素{ai−1,ai,ai+1}的山/谷状态。我们认为,对于有效i(1<i<n),将ai改为ai−1或ai+1是最佳的。

设x是ai的值,使得元素{ai−1,ai,ai+1}之间的山/谷的数量最小化。现在,如果x<max(ai−1,ai+1),我们可以设置x:=min(ai−1,ai+1),而无需将任何非山/非谷元素更改为山/谷。类似地,如果x>min(ai−1,ai+1),我们可以设置x:=max(ai−1,ai+1)。由此证明。

最终解决方案如下。预先计算原始数组中的山丘和山谷数。然后,对于每个有效索引i,在设置ai:=ai−1和ai:=ai+1时,计算元素{ai−1,ai,ai+1}的丘陵/山谷数量的变化,并相应地更新最小答案。

对于模拟题函数的分装是非常关键的
要确定当前方案一定是可行的,然后对事件及进行优化

#include <bits/stdc++.h>
using namespace std;
#define int long long

const int N = 3e5;
int a[N], n;

int isValley(int i) {
    return (i > 0 && i < n - 1 && a[i] < a[i - 1] && a[i] < a[i + 1]);
}

int isHill(int i) {
    return (i > 0 && i < n - 1 && a[i] > a[i - 1] && a[i] > a[i + 1]);
}

int solveTestCase() {
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> a[i];

    int is[n] = {};
    int s = 0;
    for (int i = 1; i < n - 1; i++) {
        if (isHill(i) || isValley(i))
            is[i] = 1, s++;
    }

    int ans = s;
    for (int i = 1; i < n - 1; i++) {
        int temp = a[i];
        a[i] = a[i - 1];
        ans = min(ans, s - is[i - 1] - is[i] - is[i + 1] + isHill(i - 1) + isValley(i - 1) + isHill(i) + isValley(i) + isHill(i + 1) + isValley(i + 1));
        a[i] = a[i + 1];
        ans = min(ans, s - is[i - 1] - is[i] - is[i + 1] + isHill(i - 1) + isValley(i - 1) + isHill(i) + isValley(i) + isHill(i + 1) + isValley(i + 1));
        a[i] = temp;
    }

    cout << ans << "\n";
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int t = 1;
    cin >> t;
    while (t--)
        solveTestCase();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值