Question 问题 P8445 射命丸文的取材之旅
给定序列 { a n } , { b n } \{a_n\},\{b_n\} {an},{bn},求一个序列 { c n } \{c_n\} {cn} 满足 ∀ i ∈ [ 1 , n ] , c i ∈ { a i , b i } \forall i\in[1,n],c_i\in\{a_i,b_i\} ∀i∈[1,n],ci∈{ai,bi},最大化
max { r − l + 1 − mex { c l , c l + 1 , … , c r − 1 , c r } } ( 1 ≤ l ≤ r ≤ n ) \max\{r-l+1-\operatorname{mex}\{c_l,c_{l+1},\dots, c_{r-1},c_r\}\}(1\le l\le r\le n) max{r−l+1−mex{cl,cl+1,…,cr−1,cr}}(1≤l≤r≤n)
并输出该式子可能的最大值。
Analysis 分析
这道题的提示有两个地方:
- 数据范围,40% 的数据中 a i = b i a_i = b_i ai=bi 直接把问题转换为给一个序列 { c n } \{c_n\} {cn} 求那个式子的最大值。
- 另一个是
mex
我们发现这玩意比较难处理,但是数据范围较小。
Solution
所以我们考虑枚举 mex
的值。设当前枚举的 mex
为
t
t
t。
考虑在 40% 的数据下,什么时候一个区间的 mex
不可为
t
t
t ,即区间内出现了
t
t
t 这个数。所以我们在当前枚举的情况下,将每一个
c
i
=
t
c_i = t
ci=t 是为一个墙,(特别地,
c
n
+
1
=
t
c_{n+1}=t
cn+1=t )任何合法的区间只能在墙内。所以我们记两个数组
l
e
n
i
len_i
leni:mex
为
i
i
i 时的最大答案,
p
r
e
i
pre_i
prei:
i
i
i 上一次出现的地方,那么就有
l
e
n
i
=
m
a
x
(
l
e
n
a
i
,
i
−
p
r
e
a
i
−
1
)
len_i=max(len_{a_i},i-pre_{a_i}-1)
leni=max(lenai,i−preai−1)。
考虑满分做法,我们会发现若
a
i
≠
b
i
a_i \neq b_i
ai=bi 是没有用的,因为若该区间 mex
为
a
i
a_i
ai,我们可以让这一位为
b
i
b_i
bi,同理若 mex
为
b
i
b_i
bi,这一位为
a
i
a_i
ai,对答案的计算毫无影响。所以我们只需要考虑
a
i
=
b
i
a_i = b_i
ai=bi 的位置,按 40% 的处理方法进行计算。
实现注意:
- 我们可以将最后一位视作一堵墙,记得把这个答案也更新在其中
Code 代码
int n,ans;
int a[N],b[N],pre[N],len[N];
int main(){
read(n);
for(rint i=1;i<=n;i++) read(a[i]);
for(rint i=1;i<=n;i++) read(b[i]);
for(rint i=1;i<=n;i++){
if(a[i]==b[i]){
len[a[i]]=max(len[a[i]],i-pre[a[i]]-1);
pre[a[i]]=i;
}
}
for(rint i=0;i<=n;i++) len[i]=max(len[i],n-pre[i]);//实现注意 1
for(rint i=0;i<=n;i++) ans=max(ans,len[i]-i);
printf("%d\n",ans);
return 0;
}