这篇文章上次修改于 833 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
题意:给定序列 $\{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;
}