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