问题描述
- 给一个两行的矩阵,要求最大的MEX值
- MEX值是指在所选的几列中未出现值的最小值
- 那么假设所选几列中既有1又有0的话他的MEX就是2,依此类推
思路分析
- 首先,我们先找出矩阵中既有000又有111的那一列,因为他的贡献为222,并且我们需要把这样的列单独拿出来(使得答案最大)
- 在进行上一步操作后,所剩下的列就是只有000000和111111的了,那么对于单独的000000,他的贡献显然为111,单独的111111,他的贡献显然为000,那么对于两列呢?
- 如果我们能找到相邻两列分别只有000,111的话,我们就选上,这样的话不会浪费000000列,并且比两列单独取的值更大
- 所以我们在进行第一步操作后,应再跑一遍矩阵,找到相邻的000000,111111对,在这里,我用的是vis数组,表明该列已经被使用,这样的话能确保不会选上之前选出来的000000或者111111,当然还有010101,101010。
- 那么还有遗漏就是,把所有的010101,101010挑出来,再把所有111111匹配后000000还有剩的话,我们需要再跑一边矩阵,找到那个未被使用的000000列的个数,加上贡献即可
代码如下
#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;
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;
}