「杂题乱刷2」CF2066B

题目链接

CF2066B Devyatkino (*1600)

解题思路

首先根据题目中的定义,你发现你选取一个没有 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;
}
posted @   wangmarui  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2024-02-13 「杂题乱刷」洛谷 P10155
点击右上角即可分享
微信分享提示