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;
}

浙公网安备 33010602011771号