D. Sorting By Multiplication
D. Sorting By Multiplication
You are given an array of length , consisting of positive integers.
You can perform the following operation on this array any number of times (possibly zero):
- choose three integers , and such that , and multiply every such that by .
Note that you can choose any integer as , it doesn't have to be positive.
You have to calculate the minimum number of operations to make the array sorted in strictly ascending order (i. e. the condition must be satisfied).
Input
The first line contains a single integer () — the number of test cases.
The first line of each test case contains one integer () — the length of the array .
The second line of each test case contains integers () — the array .
Additional constraint on the input: the sum of over all test cases does not exceed .
Output
For each test case, print one integer — the minimum number of operations required to make 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:
- , , ;
- , , ;
- , , .
After these operations, the array becomes .
In the second test case, we can perform one operation as follows:
- , , ;
- , , .
After these operations, the array becomes .
In the third test case, the array is already sorted.
解题思路
首先最终结果无非就只有种,全是正数,全是负数,某个前缀是负数剩下的是正数。
如果最终所有元素均为正数,那么从头开始遍历数组,如果发现,那么至少要执行一次操作使得。由于此时已经满足严格递增的关系,那么我们令后缀均乘上一个正数,使得且后缀的元素相对大小不变。由于乘上的数是正数,因此结果只会变大,如果改变后缀元素的相对大小(即不选择整个后缀乘上这个数),那么只会让某个位置的前一个数变大而后一个数变小,这样反而还要再执行多一次操作。
如果最终所有元素均为负数,那么除了让整个序列变成严格递增外还要将每个数变成负数,可以等价于先将整个序列变成严格递减,再将整个序列乘上一个负数。与上面的做法类似,从头开始遍历,如果发现,由于乘上一个正数会使得结果变大,因此将整个前缀乘上一个正数即可。
如果最终某个前缀是负数,后缀是正数,那么我们可以枚举分界点是哪个,然后将分界点前的元素按上面的做法变成严格递增的负数,再将分界点后的元素按上面的做法变成严格递增的正数。在枚举分界点后为了能在的复杂度得到结果,我们需要快速知道前缀有多少个相邻的数对满足以及后缀有多少个相邻的数对满足。假设我们预处理得到前缀和表示满足的个数,表示满足的个数,如果分界点是,那么需要执行的操作总数量就是。
另外如果最终所有元素均为正数,那么需要执行的操作次数就是。如果最终所有元素均为正数,那么需要执行的操作次数就是。
AC代码如下,时间复杂度为:
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
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17673797.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2022-09-02 环形石子合并