Problem - D - Codeforces
给定一个长度为n的数组a,由正整数组成。
您可以对该数组执行以下操作任意次数(可能为零):
选择三个整数l、r和x,使得1≤l≤r≤n,并将满足l≤i≤r的每个ai乘以x。
请注意,您可以选择任何整数作为x,它可以是正数也可以是负数。
您需要计算将数组a排序为严格升序所需的最小操作次数(即满足a1<a2<⋯<an条件)。
输入:
第一行包含一个整数t(1≤t≤104)- 测试用例的数量。
每个测试用例的第一行包含一个整数n(1≤n≤2⋅105)- 数组a的长度。
每个测试用例的第二行包含n个整数a1,a2,…,an(1≤ai≤109)- 数组a。
输入的附加约束条件:所有测试用例的n之和不超过2⋅105。
输出:
对于每个测试用例,打印一个整数-使a排序为严格升序所需的最小操作次数。
示例:
输入: 3 5 1 1 2 2 2 6 5 4 3 2 5 1 3 1 2 3
输出: 3 2 0
注意:
在第一个测试用例中,我们可以进行如下操作:
Plain Text
l=2,r=4,x=3;
l=4,r=4,x=2;
l=5,r=5,x=10。
执行这些操作后,数组a变为[1,3,6,12,20]。
在第二个测试用例中,我们可以执行以下一个操作:
Plain Text
l=1,r=4,x=−2;
l=6,r=6,x=1337。
执行这些操作后,数组a变为[−10,−8,−6,−4,5,1337]。
在第三个测试用例中,数组a已经是排序的。
题解:
经过对一些构造的样例操作,我们发现改变的次数只与相邻位置的相对大小有关,假设当前数<=前一个数,那么我们总可以把后面所有数乘一个很大的,这样就能保证递增,经过实验我们发现这是可行的
但是还有一点不太好想,我们可以把一段前缀是完全单调递减的,乘负数,这一段就变成了单调递增的,
并与后面的数组拼接,
因此我们只需要统计前缀有多少非单调递减的相对大小关系
后缀有多少非单调递增的相对大小关系
如果要反转前面为负数,会乘负数,所以加1
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[200040];
void solve()
{
int n;
cin >> n;
for(int i = 1;i <= n;i++)
{
cin >> a[i];
}
vector<int> l(n + 10),r(n + 10);
for(int i = 2;i <= n;i++)
{
l[i] = l[i - 1] + (a[i] >= a[i - 1]);
}
int ans = 1e9;
for(int i = n - 1;i >= 1;i--)
{
r[i] = r[i + 1] + (a[i] >= a[i + 1]);
}
ans = min(ans,r[1]);
for(int i = 1;i <= n;i++)
{
ans = min(ans,l[i] + 1 + r[i + 1]);
}
cout <<ans <<"\n";
}
signed main()
{
int t = 1;
cin >> t ;
while(t--)
{
solve();
}
}