似乎跟 365751 的方法差不多?
对于 s1 和 s2 各开一个并查集,如果相邻两个数可交换,那么合并它们。分别统计两个并查集内所含 0/1 的个数
然后对于所有 1≤i≤n,如果 i 所在的交换块内能“调出”相同的数,那么答案加一。
能通过民间数据,但感觉很假,希望有大佬能给出简要的证明或者 Hack。
void solve()
{
cin >> n;
cin >> (s1 + 1) >> (s2 + 1) >> (t1 + 1) >> (t2 + 1);
for(int i = 1;i <= n;i++)
{
c0[i] = c1[i] = d0[i] = d1[i] = 0;
fa1[i] = fa2[i] = i;
}
for(int i = 2;i <= n;i++)
{
if(t1[i] == '1' && t1[i - 1] == '1') fa1[i] = fa1[i - 1];
if(t2[i] == '1' && t2[i - 1] == '1') fa2[i] = fa2[i - 1];
}
for(int i = 1;i <= n;i++)
{
if(s1[i] == '0') c0[fa1[i]]++;
else if(s1[i] == '1') c1[fa1[i]]++;
if(s2[i] == '0') d0[fa2[i]]++;
else if(s2[i] == '1') d1[fa2[i]]++;
}
int ans = 0;
for(int i = 1;i <= n;i++)
{
int fx = fa1[i], fy = fa2[i];
if(d0[fy] && c0[fx])
{
ans++;
d0[fy]--;
c0[fx]--;
}
else if(d1[fy] && c1[fx])
{
ans++;
d1[fy]--;
c1[fx]--;
}
}
cout << ans << endl;
}