以下为我的代码
第一次交的时候mx是1e5+5 RE只得了70分
再交1e6就是全对了,但是n不是1e5嘛
(下面有我的代码思路)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int mx = 1e6 + 5;
int n, b[mx][2], idx1, idx2, ans, tt;
char s[mx][2], f[mx][2];
struct ifmt {
int c0, c1;
} cnt[mx][2];
int main() {
cin >> tt;
while (tt--) {
cin >> n;
idx1 = idx2 = ans = 0;
memset(cnt, 0, sizeof(cnt));
memset(b, 0, sizeof(b));
for (int i = 1; i <= n; i++) cin >> s[i][0];
for (int i = 1; i <= n; i++) cin >> s[i][1];
for (int i = 1; i <= n; i++) cin >> f[i][0];
for (int i = 1; i <= n; i++) cin >> f[i][1];
for (int i = 1; i <= n; i++) {//记录每个组的信息
if (f[i][0] == '0') {
idx1++;//组的编号
b[i][0] = idx1;//属于哪个组
if (s[i][0] == '1') cnt[idx1][0].c1++;
else cnt[idx1][0].c0++;
idx1++;
} else {
b[i][0] = idx1;
if (s[i][0] == '1') cnt[idx1][0].c1++;
else cnt[idx1][0].c0++;
}
if (f[i][1] == '0') {
idx2++;
b[i][1] = idx2;
if (s[i][1] == '1') cnt[idx2][1].c1++;
else cnt[idx2][1].c0++;
idx2++;
} else {
b[i][1] = idx2;
if (s[i][1] == '1') cnt[idx2][1].c1++;
else cnt[idx2][1].c0++;
}
}
for (int i = 1; i <= n; i++) {
if (f[i][0] == '0' && f[i][1] == '0' && s[i][0] == s[i][1]) {
ans++;
continue;
} else {//其实这上面的判断比较多余但我为了贴合考场代码
if (cnt[b[i][0]][0].c0 >= 1 && cnt[b[i][1]][1].c0 >= 1) {
ans++;
cnt[b[i][0]][0].c0--;
cnt[b[i][1]][1].c0--;
} else if (cnt[b[i][0]][0].c1 >= 1 && cnt[b[i][1]][1].c1 >= 1) {
ans++;
cnt[b[i][0]][0].c1--;
cnt[b[i][1]][1].c1--;
}
}
}
cout << ans << endl;
}
return 0;
}
思路
以不能移动的字符为端点将两个字符串分组,不能移动的字符自己也算一个组,记录每个组内 0 和 1 的个数以及每个位置的字符属于哪个组(每个组内 0 和 1 可以随意流动)对于位置相同的 s[i][0] 和 s[i ][1]若其属于的组内有的 1 个数 >=1 或者有的 0 个数 >=1 那么就 ++ans 并 −− 这个组内所有的 1/0 个数(假装它固定了)
样例解释
011101
111010
111010
101101
分组后长这样,各组内数字可随意变换位置,但是不能串组
011 1 0 1
1 1 10 1 0
我是菜鸡代码应该还有很多可优化的地方,大家看着玩吧