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;
}
posted @ 2025-07-30 23:03  WHUStar  阅读(5)  评论(0)    收藏  举报