D. Sorting By Multiplication(贪心)

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();
	}
}

猜你喜欢

转载自blog.csdn.net/m0_64158084/article/details/132699841