CF2066B White Magic

CF2066B White Magic

思路

超级诈骗题。

显然当不选 \(0\) 时子序列一定合法,因为此时 \(\text{mex}=0\),且子序列中的最小值至少为 \(1\)

其次选择 \(0\) 的个数不能超过 \(1\),因为当 \(0\) 的个数超过 \(1\) 时,可以将子序列分成两段包含 \(0\) 的序列,则其中一段的 \(\min=0\),另一段的 \(\text{mex}\) 至少为 \(1\),显然不满足条件。且选 \(0\) 时总是选择最左边的 \(0\) 最好,这样可以使得 \(\text{mex}\neq 0\) 时的 \(i\) 最小。

由此我们可以知道最大答案只可能是不选 \(0\) 构成的子序列或只选 \(1\)\(0\) 构成的子序列的长度,按照题意模拟选择 \(0\) 后序列的合法性即可。

代码

#include <bits/stdc++.h>
using namespace std;
int T,n,a[200005],mn[200005],c[200005],ans,tot;
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr),cout.tie(nullptr);
	cin>>T;
	while(T--){
		cin>>n;
		tot=n+1;
		mn[0]=INT_MAX;
		for(int i=0;i<=n;i++)
			c[i]=0;
		for(int i=1;i<=n;i++){
			cin>>a[i];
			if(a[i]==0){
				if(tot!=n+1) a[i]=INT_MAX;
				tot--;
			}
			mn[i]=min(mn[i-1],a[i]);
		}
		for(int nw=0,i=n;i>=1;i--){
			if(a[i]<n) c[a[i]]++;
			while(c[nw]) nw++;
			if(mn[i-1]<nw){
				tot--;
				break;
			}
		}
		cout<<min(n,tot)<<endl;
	}
	return 0; 
}
posted @ 2025-03-26 11:03  WuMin4  阅读(8)  评论(0)    收藏  举报