射命丸文的取材之旅题解

射命丸文的取材之旅

原题传送门

题目描述

给定序列 { 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{rl+1mex{cl,cl+1,,cr1,cr}}(1lrn)

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

输入格式

第一行一个正整数 n n n,表示每一份新闻中的新闻条数。

第二行 n n n非负整数表示第一份新闻中每一条新闻的吸引力,即 a 1 , a 2 … , a n − 1 , a n a_1,a_2\dots ,a_{n-1},a_n a1,a2,an1,an

第三行 n n n非负整数表示第二份新闻中每一条新闻的吸引力,即 b 1 , b 2 … , b n − 1 , b n b_1,b_2\dots ,b_{n-1},b_n b1,b2,bn1,bn

输出格式

输出一个整数,表示报刊的最大的综合影响力会是多少。

思路

  • 对于20pts,可以暴力求解。

  • 对于另外的 40 p t s 40pts 40pts,因为 ∀ 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}所以数列c唯一,我们考虑将序列中出现的数字标红,将未出现过的数字标黑 ,可以发现,红色数字将整个序列分解成了很多个黑色的段,而且显而易见黑色段里的 m e x mex mex小于等于红色数字。然后,我们考虑枚举 m e x mex mex ,(小于等于不好处理)就假设红色数字是前面黑色段子的 m e x mex mex,(贪心的选择最大的子段长度,就是上一次出现的红色数字的位置+1到当前枚举到的红色数字-1,这里处理了前面及中间的黑色段子),最后再枚举一遍1到n,取他们为 m e x mex mex,更新答案,取上一次 x x x出现的地方+1到n。(这里处理了后面的黑色段子)。

    你可能会发现,这可能会枚举到虚假的答案,即 m e x mex mex是小于红色数字的。但这不重要,这种虚假的答案会被更优的答案覆盖掉。

    如: c = 1 , 1 , 4 , 5 , 1 , 4 c={1,1,4,5,1,4} c=1,1,4,5,1,4

    那么,枚举到最后一个4的时候,取得子段就是 5 , 1 {5,1} 5,1,可, m e x ( 5 , 1 ) mex(5,1) mex(5,1)应是0,可我们假设的 m e x mex mex是4,不符合要求,但这无妨,因为计算出来的贡献是 − 2 -2 2根本无法更新答案。接着举例,你会发现,这个虚假的 m e x mex mex所造成虚假的贡献要么都无法覆盖前面的答案,要么会被后面的答案覆盖掉,因此,正确性可以保证。

    code

    #include<bits/stdc++.h>
    using namespace std;
    int n,a[1000007],b[1000007],l[1000007],ans;
    int main(){
    	cin >> n;
    	for (int i = 1;i <= n;i++)
    		cin >> a[i];
    	for (int i=1;i<=n;i++)
    		cin >> b[i];
    	for (int i=1;i<=n;i++){
    		ans=max(ans,i - l[a[i]] - 1 - a[i]);
            /*
            上一次出现的位置是l[a[i]],这一次出现的位置是i,
            而原式是 (i-1) - (l[a[i]]+1) -1 - a[i],
            化简就是 i - l[a[i]] - 1 - a[i]。
            */
    		l[a[i]] = i; // 将a[i]出现的位置记下方便下一次操作
    	}
    	for (int i = 0;i <= n;i++)
    		ans = max(ans,n - l[i] - i);
        	/*
        	原式n - (l[i] + 1) - 1 - i;
        	*/
    	cout << ans << endl;
        return 0;
    }
    
  • 对于 100 p t s 100pts 100pts,我们发现,可以选择 a i 或 b i a_i或b_i aibi,即序列 c i c_i ci不一定。但通过观察我们可以发现,只有 a i = b i a_i=b_i ai=bi时才会有可能影响到我们的 m e x mex mex,其他数字没有影响。所以,我们考虑延续前面的做法,但我们的红色数字仅在 a i = b i a_i=b_i ai=bi时将这个数字标红,将其他数字标黑,然后还是假设 m e x mex mex等于红色数字,照上文枚举即可。

Code

#include<bits/stdc++.h>
using namespace std;
int n,a[1000007],b[1000007],l[1000007],ans;
int main(){
	cin >> n;
	for (int i = 1;i <= n;i++)
		cin >> a[i];
	for (int i=1;i<=n;i++)
		cin >> b[i];
	for (int i=1;i<=n;i++){
		if(a[i] != b[i]) continue;
		ans = max(ans,i - l[a[i]] - 1 - a[i]);
        /*
        上一次出现的位置是l[a[i]],这一次出现的位置是i,
        而原式是 (i-1) - (l[a[i]]+1) -1 - a[i],
        化简就是 i - l[a[i]] - 1 - a[i]。
        */
		l[a[i]] = i; // 将a[i]出现的位置记下方便下一次操作
	}
	for (int i = 0;i <= n;i++)
		ans = max(ans,n - l[i] - i);
    	/*
    	原式n - (l[i] + 1) - 1 - i;
    	*/
	cout << ans << endl;
    return 0;
}

补充

你可能会发现,删掉ans = max(ans,i - l[a[i]] - 1 - a[i])这一行,代码仍然AC,这是为什么呢?

当然是因为数据水,不信你可以试一下这一组样例。

在这里插入代码片
6
1 2 3 4 5 6 0 1 2 3 4
1 2 3 4 5 6 0 1 2 3 4
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值