P8445 射命丸文的取材之旅

Question 问题 P8445 射命丸文的取材之旅

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

\[\max\{r-l+1-\operatorname{mex}\{c_l,c_{l+1},\dots, c_{r-1},c_r\}\}(1\le l\le r\le n) \]

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

Analysis 分析

这道题的提示有两个地方:

  1. 数据范围,40% 的数据中 \(a_i = b_i\) 直接把问题转换为给一个序列 \(\{c_n\}\) 求那个式子的最大值。
  2. 另一个是 mex 我们发现这玩意比较难处理,但是数据范围较小。

Solution

所以我们考虑枚举 mex 的值。设当前枚举的 mex\(t\)

考虑在 40% 的数据下,什么时候一个区间的 mex 不可为 \(t\) ,即区间内出现了 \(t\) 这个数。所以我们在当前枚举的情况下,将每一个 \(c_i = t\) 是为一个墙,(特别地,\(c_{n+1}=t\) )任何合法的区间只能在墙内。所以我们记两个数组 \(len_i\)mex\(i\) 时的最大答案,\(pre_i\)\(i\) 上一次出现的地方,那么就有 \(len_i=max(len_{a_i},i-pre_{a_i}-1)\)

考虑满分做法,我们会发现若 \(a_i \neq b_i\) 是没有用的,因为若该区间 mex\(a_i\),我们可以让这一位为 \(b_i\),同理若 mex\(b_i\),这一位为 \(a_i\),对答案的计算毫无影响。所以我们只需要考虑 \(a_i = b_i\) 的位置,按 40% 的处理方法进行计算。

实现注意:

  1. 我们可以将最后一位视作一堵墙,记得把这个答案也更新在其中

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;
}
posted @ 2024-05-29 21:54  Mr_Azz  阅读(5)  评论(0编辑  收藏  举报