Codeforces 1385C - Make It Good(思维)

C. Make It Good

time limit per test1 second
memory limit per test256 megabytes
input standard input
output standard output
You are given an array a consisting of n integers. You have to find the length of the smallest (shortest) prefix of elements you need to erase from a to make it a good array. Recall that the prefix of the array a=[a1,a2,…,an] is a subarray consisting several first elements: the prefix of the array a of length k is the array [a1,a2,…,ak] (0≤k≤n).

The array b of length m is called good, if you can obtain a non-decreasing array c (c1≤c2≤⋯≤cm) from it, repeating the following operation m times (initially, c is empty):

select either the first or the last element of b, remove it from b, and append it to the end of the array c.
For example, if we do 4 operations: take b1, then bm, then bm−1 and at last b2, then b becomes [b3,b4,…,bm−3] and c=[b1,bm,bm−1,b2].

Consider the following example: b=[1,2,3,4,4,2,1]. This array is good because we can obtain non-decreasing array c from it by the following sequence of operations:

take the first element of b, so b=[2,3,4,4,2,1], c=[1];
take the last element of b, so b=[2,3,4,4,2], c=[1,1];
take the last element of b, so b=[2,3,4,4], c=[1,1,2];
take the first element of b, so b=[3,4,4], c=[1,1,2,2];
take the first element of b, so b=[4,4], c=[1,1,2,2,3];
take the last element of b, so b=[4], c=[1,1,2,2,3,4];
take the only element of b, so b=[], c=[1,1,2,2,3,4,4] — c is non-decreasing.
Note that the array consisting of one element is good.

Print the length of the shortest prefix of a to delete (erase), to make a to be a good array. Note that the required length can be 0.

You have to answer t independent test cases.

Input

The first line of the input contains one integer t (1≤t≤2⋅104) — the number of test cases. Then t test cases follow.

The first line of the test case contains one integer n (1≤n≤2⋅105) — the length of a. The second line of the test case contains n integers a1,a2,…,an (1≤ai≤2⋅105), where ai is the i-th element of a.

It is guaranteed that the sum of n does not exceed 2⋅105 (∑n≤2⋅105).

Output

For each test case, print the answer: the length of the shortest prefix of elements you need to erase from a to make it a good array.

Example
input
5
4
1 2 3 4
7
4 3 3 8 4 5 2
3
1 1 1
7
1 3 1 4 5 3 2
5
5 4 3 2 3
outputCopy
0
4
0
2
3

Note

In the first test case of the example, the array a is already good, so we don’t need to erase any prefix.

In the second test case of the example, the initial array a is not good. Let’s erase first 4 elements of a, the result is [4,5,2]. The resulting array is good. You can prove that if you erase fewer number of first elements, the result will not be good.

题目大意:

给出 t 组测试样例,每组输入一个长度为 n 的数组,需要这个数组的一定长度的前缀使得剩余数组只从前后取数,能形成一个有序的序列。求删除的最小长度。

解题思路:

这道题我是分了3种情况的。

  • 如果给出的数组不递增,则ans = 0
  • 如果给出的数组不递减 ,则ans = 0
  • 正常情况 有增有减

对于前两种情况遍历一下即可,对于第三种情况,可以倒着找,找最后一个过山车数组(中间高两边低),用总长度减去过山车数组的长度即可。AC代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <vector>
using namespace std;
const int N = 2e5 + 50;
typedef long long ll;
vector<int> v;
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		v.clear();
		int n;
		cin >> n;
		for (int i = 0; i < n; i++)
		{
			int s;
			cin >> s;
			v.push_back(s);
		}
		int ans1 = 1, ans2 = 1, ans3 = 1;
		for (int i = n - 2; i >= 0 ; i --)
		{
			if (v[i] >= v[i + 1])
			  ans1++;
			else
			  break;
		}
		for (int i = n - 2; i >= 0 ; i --)
		{
			if (v[i] <= v[i + 1])
			  ans2++;
			else
			  break;
		}
		if (ans1 == v.size() || ans2 == v.size())//两种特殊情况
		{
			cout << 0 << endl;
			continue;
		}
		bool flag = true;
		for (int i = n - 2; i >= 0; i --)//倒着找
		{
			if (flag)
			{
				if (v[i] >= v[i + 1])
				  ans3++;
				else
				{
					ans3++;
					flag = false;
				}
			}
			else
			{
				if (v[i] <= v[i + 1])
				  ans3++;
				else
				  break;
			}
		}
		int len = max(ans1, max(ans2, ans3));
		len = v.size() - len;
		cout << len << endl;
	}
	return 0;
}

优化:

对于这种写法显然太麻烦了,可以把三种情况结合一下,直接倒着找,先找从后往前第一个连续不降的序列,存一下位置,再接着这个位置找一下不增的序列,最后直接输出存的位置即可。标程:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
using namespace std;
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		cin >> n;
		vector<int > v;
		for (int i = 1; i <= n; i ++)
		{
			int s;
			cin >> s;
			v.push_back(s);
		}
		int pos = n - 1;
		while (pos > 0 && v[pos - 1] >= v[pos])  pos--;//先找不降的
		while (pos > 0 && v[pos - 1] <= v[pos])  pos--;//再找不增的
		cout << pos << endl;
	}
	return 0;
}
posted @ 2020-07-18 18:05  Hayasaka  阅读(66)  评论(0编辑  收藏  举报