这篇文章上次修改于 698 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

题目传送门

题意:给定序列 $\{a_n\},\{b_n\}$,求一个序列 $\{c_n\}$ 满足 $\forall i\in[1,n],c_i\in\{a_i,b_i\}$,最大化

并输出该式子可能的最大值。

其中 $\operatorname{mex}\{c_l,c_{l+1},\dots,c_{r-1},c_r\}$ 指的是 $c_l,c_{l+1},\dots,c_{r-1},c_r$ 中没有出现过的最小非负整数

看到数据范围有一点奇怪$0
\leq a_i,b_i\leq n$

为什么会限制$a,b$取值范围。正解:枚举mex。

其实也不太严谨,如果去掉最小的条件从0~n枚举作为没有出现的那个数,会出现问题吗?

没有。因为在最终的序列中是要剪掉$mex$的。所以$mex$是不是最小的没必要考虑,因为更小的$mex$是被考虑了的。

问题变为:确定一个区间使得区间的数都不等于m(0$\leq$m$\leq$n),区间要尽可能大。

如果所有$a_i$!=$b_i$,那么总有方案是的能选出c序列使得其中每一个数不等于任意一个数,因为假如$mex=1$,考虑第$i$个位置,如果$a_i=mex$,那$b_i$一定不等于$mex$。总会找到一个数满足情况。

加上 $a_i=b_i$ 的情况,那如果 $a_i=b_i!=mex$ 并无大碍。
如果 $a_i=b_i=mex$那就必须从i中间断开成为两个序列,分别考虑对答案的贡献。

用vector来存$a_i=b_i=mex$的所有下标

//g++  7.4.0

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define int long long
using namespace std;
int a[1000005];
vector<int>to[1000005];
inline int read()
{
	int x=0;
	bool flag=1;
	char c=getchar();
	while(c<'0'||c>'9')
	{
		if(c=='-')
			flag=0;
		c=getchar();
	}
	while(c>='0'&&c<='9')
	{
		x=(x<<1)+(x<<3)+c-'0';
		c=getchar();
	}
	return (flag?x:~(x-1));
}
signed main()
{
    int n;
    n=read();
    int ans=0;
    to[0].push_back(0); 
    for(int i=1;i<=n;i++){
    	a[i]=read();
    	to[i].push_back(0);
	}
//	int t=0;
	for(int i=1;i<=n;i++){
		int temp;
		temp=read();
		if(a[i]==temp){
			to[a[i]].push_back(i);
		}
	}
	for(int i=0;i<=n;i++){
		to[i].push_back(n+1);
	}
	for(int i=0;i<=n;i++){
		for(int j=1;j<to[i].size();j++){
			ans=max(ans,to[i][j]-1-to[i][j-1]-i);
		}
	}
	printf("%lld",ans);
    return 0;
}