题目大意:
给定一个包含 n 个正整数 a1,a2,…,an 的数组。
在一项操作中,您可以执行以下操作:
选择任何整数 x。
对于所有使 ai=x 的 i,执行 ai:=0(将 0 分配给 ai)。
找到以非递减顺序对数组进行排序所需的最小操作数。
想法:
从后往前遍历数组,当第一次有 a[ i - 1] > a[ i ] 时,将1 ~ i - 1 之间的数全都清为0,过程中再将改变的数作st = true, 再从1开始将所有标记的数清为0,再重复一遍操作,这样可以保证得到的数组只有两种情况:(1)数组全为0,(2)数组前面一段为0,后一段为非递减数列;
证明:
从后往前可以保证操作次数最少,
第一次操作可以保证数组前一段为0,后一段非递减,这样清为0之后可以保证后一段除了0的数是非递减的,
第二次操作之后直接可以保证前一段都为0,后一段的数都满足 a[ i - 1 ] <= a[ i ]
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <climits>
using namespace std;
#define Bug return
#define Free 0
#define mst(x, y) memset(x, y, sizeof x)
#define X first
#define Y second
#define int long long
#define FAST ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 200010, INF = 0x3f3f3f3f;
const double EPS = 1e-6;
typedef pair<int, int> PII;
int T, n, idx;
int a[N];
bool st[N];
signed main()
{
FAST;
cin >> T;
while (T--)
{
idx = 0;
mst(st, false);
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = n; i > 1; i--)
{
if (a[i] < a[i - 1])
{
i--;
while (i)
{
if (!st[a[i]])
{
st[a[i]] = true;
idx++;
}
a[i] = 0;
i--;
}
break;
}
}
for (int i = 1; i <= n; i++)
if (st[a[i]])
a[i] = 0;
for (int i = n; i > 1; i--)
{
if (a[i] < a[i - 1])
{
i--;
while (i)
{
if (!st[a[i]] && a[i])
{
st[a[i]] = true;
idx++;
}
a[i] = 0;
i--;
}
break;
}
}
cout << idx << endl;
}
Bug Free;
}