不用管这个代码的作用,求 hack 即可。 数据不要太大, n 最好在 10 以内,最好满足 B 性质。
#include <bits/stdc++.h>
using namespace std;
const int N = 110000;
int t, n, ans, tot;
//h1,h2记录当前是可交换/不可交换
//a10,a11,a20,a21记录第1/2条字符串当前这一组的0/1个数
//sum11,sum10,sum21,sum20记录当前字符串的大组的1/0的个数
//id1,id2记录当前小组下标所指向的大组的小标的值
int h1[N], h2[N], a11[N], a10[N], a21[N], a20[N], sum10[N], sum20[N], sum11[N], sum21[N], cnt1, cnt2, id1[N], id2[N];
char s1[N], s2[N];
char t1[N], t2[N];
int main() {
// freopen("v.txt", "r", stdin);
// freopen("ans.txt", "w", stdout);
scanf("%d", &t);
while (t--) {
ans = 0;
tot = 0;
cnt1 = 0, cnt2 = 0;
scanf("%d", &n);
scanf("%s\n%s", s1 + 1, s2 + 1);
scanf("%s\n%s", t1 + 1, t2 + 1);
for (int i = 1; i <= n; i++) {
if (t1[i] == '1' && t1[i - 1] != '1' && t1[i + 1] != '1') t1[i] = '0';
if (t2[i] == '1' && t2[i - 1] != '1' && t2[i + 1] != '1') t2[i] = '0';
}
int lst = 1, yi1 = s1[1] - '0', yi2 = s2[1] - '0';
for (int i = 2; i <= n; i++) {
if (t1[i] != t1[i - 1] || t2[i] != t2[i - 1]) {
if (t1[i - 1] == '1') {
h1[++tot] = 1;
} else h1[++tot] = 0;
if (t2[i - 1] == '1') {
h2[tot] = 1;
} else h2[tot] = 0;
a11[tot] = yi1, a10[tot] = i - lst - yi1;
a21[tot] = yi2, a20[tot] = i - lst - yi2;
yi1 = s1[i] - '0', yi2 = s2[i] - '0';
lst = i;
} else {
yi1 += s1[i] - '0', yi2 += s2[i] - '0';
}
}
if (t1[n] == '1') h1[++tot] = 1;
else h1[++tot] = 0;
if (t2[n] == '1') h2[tot] = 1;
else h2[tot] = 0;
a11[tot] = yi1, a10[tot] = n - lst + 1 - yi1;
a21[tot] = yi2, a20[tot] = n - lst + 1 - yi2;
int one1 = 0, one2 = 0;
int zer1 = 0, zer2 = 0;
for (int i = 1; i <= tot + 1; i++) {
if (i > 1 && h1[i - 1] == 1 && h1[i] == 0) {
cnt1++;
sum11[cnt1] = one1;
sum10[cnt1] = zer1;
one1 = 0;
zer1 = 0;
} else if (h1[i] == 1) {
one1 += a11[i];
zer1 += a10[i];
id1[i] = cnt1 + 1;
}
if (i > 1 && h2[i - 1] == 1 && h2[i] == 0) {
cnt2++;
sum21[cnt2] = one2;
sum20[cnt2] = zer2;
one2 = 0;
zer2 = 0;
} else if (h2[i] == 1) {
one2 += a21[i];
zer2 += a20[i];
id2[i] = cnt2 + 1;
}
}
// cout << sum21[1] << endl;
for (int i = 1; i <= tot; i++) {
if (h1[i] == 0 && h2[i] == 0) continue;//上下都不可交换单独处理
if (h1[i] == 1 && h2[i] == 1) {//上下均可交换
// if (i == 5) cout << ans << endl;
if (h1[i + 1] == 0 && h2[i + 1] == 0) {//上下的下一个都不可交换
ans += min(sum11[id1[i]], sum21[id2[i]]) + min(sum10[id1[i]], sum20[id2[i]]);
} else if (h1[i + 1] == 1 && h2[i + 1] == 0) {//上的下一个可交换
ans += min(sum11[id1[i]], sum21[id2[i]]) + min(sum10[id1[i]], sum20[id2[i]]);
int t1 = min(sum11[id1[i]], sum21[id2[i]]);
int t2 = min(sum10[id1[i]], sum20[id2[i]]);
if (min(sum11[id1[i]], sum21[id2[i]]) + min(sum10[id1[i]], sum20[id2[i]]) != a11[i] + a10[i]) {
if (sum11[id1[i]] - t1) sum11[id1[i]] -= a11[i] + a10[i] - (min(sum11[id1[i]], sum21[id2[i]]) + min(sum10[id1[i]], sum20[id2[i]]));
else sum10[id1[i]] -= a11[i] + a10[i] - (min(sum11[id1[i]], sum21[id2[i]]) + min(sum10[id1[i]], sum20[id2[i]]));
}
sum11[id1[i]] -= t1;
sum10[id1[i]] -= t2;
} else if (h1[i + 1] == 0 && h2[i + 1] == 1) {//下的下一个可交换
// if (i == 5) cout << min(sum10[id1[i]], sum20[id2[i]]) << endl;
// if (i == 5) cout << ans << endl;
ans += min(sum11[id1[i]], sum21[id2[i]]) + min(sum10[id1[i]], sum20[id2[i]]);
int t1 = min(sum11[id1[i]], sum21[id2[i]]);
int t2 = min(sum10[id1[i]], sum20[id2[i]]);
if (min(sum11[id1[i]], sum21[id2[i]]) + min(sum10[id1[i]], sum20[id2[i]]) != a11[i] + a10[i]) {
if (sum21[id2[i]] - t1) sum21[id2[i]] -= a11[i] + a10[i] - (min(sum11[id1[i]], sum21[id2[i]]) + min(sum10[id1[i]], sum20[id2[i]]));
else sum20[id2[i]] -= a11[i] + a10[i] - (min(sum11[id1[i]], sum21[id2[i]]) + min(sum10[id1[i]], sum20[id2[i]]));
}
sum21[id2[i]] -= t1;
sum20[id2[i]] -= t2;
}
// if (i == 4) cout << ans << endl;
} else if (h1[i] == 1 && h2[i] == 0) {//上可以交换
ans += min(sum11[id1[i]], a21[i]) + min(sum10[id1[i]], a20[i]);
int t1 = min(sum11[id1[i]], a21[i]);
int t2 = min(sum10[id1[i]], a20[i]);
if (min(sum11[id1[i]], a21[i]) + min(sum10[id1[i]], a20[i]) != a11[i] + a10[i]) {
if (sum11[id1[i]] - t1) sum11[id1[i]] -= a11[i] + a10[i] - (min(sum11[id1[i]], a21[i]) + min(sum10[id1[i]], a20[i]));
else sum10[id1[i]] -= a11[i] + a10[i] - (min(sum11[id1[i]], a21[i]) + min(sum10[id1[i]], a20[i]));
// if (sum11[id1[i]] - t1) cout << i << endl;
// if (i == 4) cout << a11[i] + a10[i] << endl;
}
sum11[id1[i]] -= t1;
sum10[id1[i]] -= t2;
// if (i == 1) cout << ans << endl;
} else if (h1[i] == 0 && h2[i] == 1) {//下可以交换
// if (i == 5) cout << sum21[1] << endl;
ans += min(a11[i], sum21[id2[i]]) + min(a10[i], sum20[id2[i]]);
int t1 = min(a11[i], sum21[id2[i]]);
int t2 = min(a10[i], sum20[id2[i]]);
if (min(a11[i], sum21[id2[i]]) + min(a10[i], sum20[id2[i]]) != a11[i] + a10[i]) {
if (sum21[id2[i]] - t1) sum21[id2[i]] -= a11[i] + a10[i] - (min(a11[i], sum21[id2[i]]) + min(a10[i], sum20[id2[i]]));
else sum20[id2[i]] -= a11[i] + a10[i] - (min(a11[i], sum21[id2[i]]) + min(a10[i], sum20[id2[i]]));
}
sum21[id2[i]] -= t1;
sum20[id2[i]] -= t2;
}
}
// cout << ans << endl;
for (int i = 1; i <= n; i++) {
if (t1[i] == '0' && t2[i] == '0') {
if (s1[i] == s2[i]) {
ans++;
}
}
}
printf("%d\n", ans);
}
return 0;
}
/*
1
11
01000100110
11011100110
11110111110
00111110000
1
8
11000111
11111000
11111000
00011111
1
16
0110010110110111
1001100110011001
1111100111111110
0001111100111100
ANS=14;
1
20
01000100111101100010
10111011000010011101
00011111001110011100
01111001111111100111
ANS=10;
1
9
101111111
100111000
110111011
011111111
//101111111
//101110000
ANS=5;
*/