White Magic

题目链接
题意:
一个序列被称为“魔法”的,如果对于序列中的每一个元素(除了最后一个),它和它之前的所有元素的最小值大于或等于它后面所有元素的MEX值。这里的MEX是指不在一个集合中出现的最小非负整数。找到给定序列的最大“魔法”子序列长度。
思路:
首先,一个“魔法”序列中最多存在一个零,因为如果存在两个以上的零,那么对于第一个零来说,它和它之前所有元素的最小值为0,而它后面所有元素的MEX值肯定大于0,不符合。对于一个没有零的序列,它一定是“魔法”序列。所以进行分类讨论,当序列没有0时,答案就是序列的长度;当序列只有一个0时,答案可能为n,可能为n-1,取决与那个0是否可以存在;当序列有多个0时,肯定最多留一个0,我们可以先留一个0,其余0全部删去,这样就和第二种情况一样了,这时,我们只需考虑留哪一个0更好,可以证明留最左边的零最优。最后来到如何判断一个含1个0的序列是否为“魔法”序列,我们可以用统计前缀最小值和后缀mex值。具体实现见代码。

点击查看代码
// #pragma GCC optimize("O3")
// #pragma G++ optimize("O3")
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define ll long long 
const int N = 2e5+5;
int arr[N];
int mex[N];
map<int,int>mp;
void solve(){
    int n;
    cin>>n;
    mp.clear();
    int g=0;
    for(int i=1;i<=n;++i){
        cin>>arr[i];
        if(arr[i]==0){
            g++;
        }
    }
    if(n==1){
        cout<<1<<endl;
        return ;
    }
    if(g==0){
        if(n<=0) n=1;
        cout<<n<<endl;
        return ;
    }
    vector<int>v;
    if(g>1){
        int x=0;
        for(int i=1;i<=n;++i){
            if(arr[i]==0){
                if(x){

                }else{
                    v.push_back(arr[i]);
                    
                }
                x++;
            }else{
                v.push_back(arr[i]);
            }
        }
        n=v.size();
        for(int i=0;i<n;++i){
            arr[i+1]=v[i];
        }
    }
    
        if(arr[n]==0){
            mex[n]=1;
        }else{
            mex[n]=0;
            mp[arr[n]]++;
        }
        for(int i=n-1;i>0;--i){
            if(arr[i]!=mex[i+1]){
                mex[i]=mex[i+1];
                mp[arr[i]]++;
            }else{
                for(int j=mex[i+1]+1;;++j){
                    if(mp[j]){

                    }else{
                        mex[i]=j;
                        break;
                    }
                }
            }
        }
        int zuixiao=arr[1];
        if(zuixiao>=mex[2]){

        }else{
            if(n-1<=0) n=2;
            cout<<n-1<<endl;;
            return ;
        }
        for(int i=2;i<n;++i){
            zuixiao=min(zuixiao,arr[i]);
            if(zuixiao>=mex[i+1]){

            }else{
                if(n-1<=0) n=2;
                cout<<n-1<<endl;
                return ;
            }

        }
        if(n<=0) n=1;
        cout<<n<<endl;
        return ;
    
    
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int _=1;
    cin>>_;
    while(_--)
    solve();
    return 0;
}
posted @ 2025-02-12 19:50  sjgigj  阅读(37)  评论(0)    收藏  举报