Codeforces1566C

问题描述

  • 给一个两行的矩阵,要求最大的MEX值
  • MEX值是指在所选的几列中未出现值的最小值
  • 那么假设所选几列中既有1又有0的话他的MEX就是2,依此类推

思路分析

  • 首先,我们先找出矩阵中既有 0 0 0又有 1 1 1的那一列,因为他的贡献为 2 2 2,并且我们需要把这样的列单独拿出来(使得答案最大)
  • 在进行上一步操作后,所剩下的列就是只有 00 00 00 11 11 11的了,那么对于单独的 00 00 00,他的贡献显然为 1 1 1,单独的 11 11 11,他的贡献显然为 0 0 0,那么对于两列呢?
  • 如果我们能找到相邻两列分别只有 0 0 0 1 1 1的话,我们就选上,这样的话不会浪费 00 00 00列,并且比两列单独取的值更大
  • 所以我们在进行第一步操作后,应再跑一遍矩阵,找到相邻的 00 00 00 11 11 11对,在这里,我用的是vis数组,表明该列已经被使用,这样的话能确保不会选上之前选出来的 00 00 00或者 11 11 11,当然还有 01 01 01 10 10 10
  • 那么还有遗漏就是,把所有的 01 01 01 10 10 10挑出来,再把所有 11 11 11匹配后 00 00 00还有剩的话,我们需要再跑一边矩阵,找到那个未被使用的 00 00 00列的个数,加上贡献即可

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int vis[maxn];
int main()
{
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
        int t;
        cin >> t;
        while (t--)
        {
                memset(vis, 0, sizeof(vis));
                int n;
                cin >> n;
                string s1, s2;
                cin >> s1;
                cin >> s2;
                //先找出0-1,1-0,标记一下
                int sum = 0;
                for (int i = 0; i < n; i++)
                {
                        if ((s1[i] == '0' && s2[i] == '1') || (s1[i] == '1' && s2[i] == '0'))
                        {
                                sum += 2;
                                vis[i] = 1;
                        }
                }
                for (int i = 0; i < n; i++)
                {
                        if (vis[i])
                        {
                                continue;
                        }
                        if (s1[i] == '1' && s2[i] == '1')
                        {
                                if (i >= 1 && vis[i - 1] != 1 && (s1[i - 1] == '0' && s2[i - 1] == '0'))
                                {
                                        sum += 2;
                                        vis[i] = 1;
                                        vis[i - 1] = 1;
                                }
                                else if (i <= n - 2 && vis[i + 1] != 1 && (s1[i + 1] == '0' && s2[i + 1] == '0'))
                                {
                                        sum += 2;
                                        vis[i] = 1;
                                        vis[i + 1] = 1;
                                }
                        }
                }
                for (int i = 0; i < n; i++)
                {
                        if (!vis[i] && (s1[i] == '0' && s2[i] == '0'))
                        {
                                sum++;
                        }
                }
                cout << sum << endl;
        }
        return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值