题解:CF2254C2 Marenol (hard version)
chenqishuo · · 题解
题意简述
给定两个长度均为
- 将子串
\texttt{001} 与\texttt{100} 互相替换; - 将子串
\texttt{011} 与\texttt{110} 互相替换。
求将
思路
由 easy version 可知,每次操作等价于将一个 1 在同奇偶性的位置之间移动 1 右移 1 左移 1 的数量和偶数位上的 1 的数量分别保持不变。
若某个奇偶性下 1 的数量不相等,则不可能变换,输出
否则,对于同一奇偶性,我们需要将 1 的位置匹配到 1 的位置。为了最小化总移动距离,显然应该按顺序配对(排序后对应),因为所有 1 等价,且移动操作不改变相对顺序(在同奇偶性中位置可交换,但最优匹配即为排序配对)。
对于每个配对,位置差为
代码
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
const int N = 2e5 + 10;
int T, n;
string a, b;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> T;
while(T --)
{
cin >> n >> a >> b;
a = " " + a + "11";
b = " " + b + "11";
long long ans = 0;
bool flag = true;
int i = 1, j = 1;
while(i <= n && j <= n)
{
while(i <= n && a[i] != '1') i += 2;
while(j <= n && b[j] != '1') j += 2;
if(i > n || j > n) break;
ans += abs(i - j) / 2;
i += 2, j += 2;
}
while(i <= n && a[i] != '1') i += 2;
while(j <= n && b[j] != '1') j += 2;
if(i <= n || j <= n) flag = false;
i = 2, j = 2;
while(i <= n && j <= n)
{
while(i <= n && a[i] != '1') i += 2;
while(j <= n && b[j] != '1') j += 2;
if(i > n || j > n) break;
ans += abs(i - j) / 2;
i += 2, j += 2;
}
while(i <= n && a[i] != '1') i += 2;
while(j <= n && b[j] != '1') j += 2;
if(i <= n || j <= n) flag = false;
if(flag) cout << ans << endl;
else cout << -1 << endl;
}
return 0;
}
原题通过记录