「杂题乱刷2」CF2066B
题目链接
解题思路
首先根据题目中的定义,你发现你选取一个没有 \(0\) 的序列是一定合法的,因为此时任意一个前缀 min 都是至少为 \(1\) 的,而任意一个后缀 mex 都为 \(0\),原式一定合法。
其次你发现你选取的子序列中最多只能有一个 \(0\),首先有一个 \(0\) 可以合法,我来讲讲为什么选取 \(2\) 个及以上的 \(0\) 是不合法的。你发现,当 \(i\) 为第一个 \(0\) 的位置时,此时前缀 min 为 \(0\),而后缀 mex 至少为 \(1\) 的,此时原式不合法。
那么我们考虑从序列中取哪个 \(0\) 最优,你发现,当你取到 \(0\) 时,那么此时你之后的 mex 都为 \(0\),符合题目条件,因此你发现越早取 \(0\) 的约束条件是最弱的,那么直接取第一个 \(0\) 是显然最优的,check 只需要按照题意模拟即可。
参考代码
#include<bits/stdc++.h>
using namespace std;
#define re register
#define ll long long
#define forl(i,a,b) for(re ll (i)=(a);i<=(b);(i)++)
#define forr(i,a,b) for(re ll (i)=(a);i>=(b);(i)--)
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl '\n'
#define QwQ return 0;
template<typename T1,typename T2>bool Max(T1&x,T2 y){if(y>x)return x=y,1;return 0;}template<typename T1,typename T2>bool Min(T1&x,T2 y){if(y<x)return x=y,1;return 0;}ll Ss=chrono::steady_clock::now().time_since_epoch().count();mt19937_64 Apple(Ss);ll rand_lr(ll l,ll r){return Apple()%(r-l+1)+l;}
ll _t_;
ll lg[1000010];
ll n;
ll S;
ll a[1000010];
ll b[1000010],k;
ll mex[1000010],minn[1000010];
ll vis[1000010];
void solve()
{
S=0;
k=0;
cin>>n;
forl(i,0,n+5)
vis[i]=0;
forl(i,1,n)
cin>>a[i],
S+=(bool)a[i];
ll id=-1;
forr(i,n,1)
if(!a[i])
id=i;
if(id==-1)
{
cout<<n<<endl;
return ;
}
forl(i,1,n)
if(a[i] || i==id)
b[++k]=a[i];
minn[0]=1e18;
forl(i,1,k)
minn[i]=min(minn[i-1],b[i]);
mex[k+1]=0;
forr(i,k,1)
{
mex[i]=mex[i+1];
if(b[i]<=n+5)
vis[b[i]]=1;
while(vis[mex[i]])
mex[i]++;
}
forl(i,1,k-1)
if(minn[i]<mex[i+1])
{
cout<<S<<endl;
return ;
}
cout<<max(S,k)<<endl;
}
int main()
{
IOS;
_t_=1;
cin>>_t_;
while(_t_--)
solve();
QwQ;
}

浙公网安备 33010602011771号