B. White Magic
链接
思路
题目大意就是对一个序列要满足$min(a_{1-i}) \geq mex(a_{i-n}) $所以自然的想法是两次预处理。
然后注意到规律:对于序列 \(a_N\),如果有两个零,显然不可能;如果没有零,那么肯定可以。{可以简单证明}
所以答案只有两种可能:加入潜在的0(就是非零的数字数目+1)或者不加(就是非零的数字数目)。
如何判断:
对于一个数,如果前面有0,那么越前面越好,如果最前面的0都无法满足,那么后面的一定不满足{可自证};如果最后一位有0,那么要求所有的子串都必须满足要求。
mex那里可以用并查集搞,但是我嫌麻烦就用了map。
代码
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define tin long long
#define itn long long
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N = 2e5 + 10;
vector<int>vt;
map<int, bool>visn;
vector<int>minn, mexn;
void solve()
{
int n; cin >> n;
vt.clear();
int vtid = -1;
minn.clear();
mexn.clear();
bool alpha = false;
visn.clear();
for (int i = 1; i <= n; i++)
{
int x; cin >> x;
if (x == 0)alpha = true;
else {
vt.push_back(x);
if (alpha and vtid == -1)vtid = vt.size() - 1;
alpha = false;
}
}
n = vt.size();
if (n == 0) {
cout << 1 << '\n';
return;
}
itn cmp = vt[0];
for (int x : vt) {
cmp = min(cmp, x);
minn.push_back(cmp);
}
cmp = 1;
for (int x = n - 1; x >= 0; x--) {
visn[vt[x]] = true;
while (visn[cmp])cmp++;
mexn.push_back(cmp);
}
int ans = n;
int jd = (vtid != -1);
if (vtid != -1) {
for (int i = 0; jd and i < vtid; i++) {
if (minn[i] < mexn[n - 2 - i])jd = 0;
}
}
if (jd == 0 and alpha) {
jd = 1;
for (int i = 0; jd and i < n - 1; i++) {
if (minn[i] < mexn[n - 2 - i])jd = 0;
}
}
cout << ans + (jd) << '\n';
}
signed main() {
IOS;
/**/int t;
cin >> t;
while (t--)
solve();
return 0;
}