D. Sorting By Multiplication

发布时间 2023-09-02 16:13:17作者: onlyblues

D. Sorting By Multiplication

You are given an array $a$ of length $n$, consisting of positive integers.

You can perform the following operation on this array any number of times (possibly zero):

  • choose three integers $l$, $r$ and $x$ such that $1 \le l \le r \le n$, and multiply every $a_i$ such that $l \le i \le r$ by $x$.

Note that you can choose any integer as $x$, it doesn't have to be positive.

You have to calculate the minimum number of operations to make the array $a$ sorted in strictly ascending order (i. e. the condition $a_1 < a_2 < \dots < a_n$ must be satisfied).

Input

The first line contains a single integer $t$ ($1 \le t \le 10^4$) — the number of test cases.

The first line of each test case contains one integer $n$ ($1 \le n \le 2 \cdot 10^5$) — the length of the array $a$.

The second line of each test case contains $n$ integers $a_1, a_2, \dots, a_n$ ($1 \le a_i \le 10^9$) — the array $a$.

Additional constraint on the input: the sum of $n$ over all test cases does not exceed $2 \cdot 10^5$.

Output

For each test case, print one integer — the minimum number of operations required to make $a$ sorted in strictly ascending order.

Example

input

3
5
1 1 2 2 2
6
5 4 3 2 5 1
3
1 2 3

output

3
2
0

Note

In the first test case, we can perform the operations as follows:

  • $l = 2$, $r = 4$, $x = 3$;
  • $l = 4$, $r = 4$, $x = 2$;
  • $l = 5$, $r = 5$, $x = 10$.

After these operations, the array $a$ becomes $[1, 3, 6, 12, 20]$.
In the second test case, we can perform one operation as follows:

  • $l = 1$, $r = 4$, $x = -2$;
  • $l = 6$, $r = 6$, $x = 1337$.

After these operations, the array $a$ becomes $[-10, -8, -6, -4, 5, 1337]$.
In the third test case, the array $a$ is already sorted.

 

解题思路

  首先最终结果无法就只有$3$种,全是正数,全是负数,某个前缀是负数剩下的是正数。

  如果最终所有元素均为正数,那么从头开始遍历数组,如果发现$a_i \geq a_{i+1}$,那么至少要执行一次操作使得$a_i < a_{i+1}$。由于此时$1 \sim i$已经满足严格递增的关系,那么我们令后缀$i+1 \sim n$均乘上一个正数,使得$a_i < a_{i+1}$且后缀的元素相对大小不变。由于乘上的数是正数,因此结果只会变大,如果改变的后缀的元素的相对大小(即不选择整个后缀乘上这个数),那么只会让某个位置的前一个数变大而后一个数变小,这样反而还要再执行多一次操作。

  如果最终所有元素均为负数,那么除了让整个序列变成严格递增外还要将每个数变成负数,可以等价于先将整个序列变成严格递减,再将整个序列乘上一个负数。与上面的做法类似,从头开始遍历,如果发现$a_i \leq a_{i+1}$,由于乘上一个正数会使得结果变大,因此将整个前缀$1 \sim i$乘上一个正数即可。

  如果最终某个前缀是负数,后缀是正数,那么我们可以枚举分界点是哪个,然后将分界点前的元素按上面的做法变成严格递增的负数,再将分界点后的元素按上面的做法变成严格递增的正数。在枚举分界点后为了能在$O(1)$的复杂度得到结果,我们需要快速知道某个前缀有多少个相邻的数对满足$a_i \leq a_{i+1}$以及某个后缀有多少个相邻的数对满足$a_i \geq a_{i+1}$。假设我们预处理得到前缀和$s_1[i]$表示$i \in [1 \sim i)$满足$a_i \geq a_{i+1}$的个数,$s_2[i]$表示$i \in [1 \sim i)$满足$a_i \leq a_{i+1}$的个数,如果分界点是$i$,那么需要执行的操作总数量就是$(s_2[i] + 1) + (s_1[n] - s_1[i+1])$。

  另外如果最终所有元素均为正数,那么需要执行的操作次数就是$s_1[n]$。如果最终所有元素均为正数,那么需要执行的操作次数就是$s_2[n]+1$。

  AC代码如下,时间复杂度为$O(n)$:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 const int N = 2e5 + 10;
 7 
 8 int a[N];
 9 int s1[N], s2[N];
10 
11 void solve() {
12     int n;
13     scanf("%d", &n);
14     for (int i = 1; i <= n; i++) {
15         scanf("%d", a + i);
16     }
17     for (int i = 2; i <= n; i++) {
18         s1[i] = s1[i - 1], s2[i] = s2[i - 1];
19         if (a[i - 1] >= a[i]) s1[i]++;
20         if (a[i - 1] <= a[i]) s2[i]++;
21     }
22     int ret = min(s1[n], s2[n] + 1);
23     for (int i = 1; i < n; i++) {
24         ret = min(ret, s2[i] + 1 + s1[n] - s1[i + 1]);
25     }
26     printf("%d\n", ret);
27 }
28 
29 int main() {
30     int t;
31     scanf("%d", &t);
32     while (t--) {
33         solve();
34     }
35     
36     return 0;
37 }

 

参考资料

  Educational Codeforces Round 154 (Rated for Div. 2)(ABCD)(模拟/思维):https://zhuanlan.zhihu.com/p/653627595

  Educational Codeforces Round 154 Editorial:https://codeforces.com/blog/entry/119964