原题链接
题目大意
给定一个 0-1
序列,有下列三种操作:
-
将某一位的
1
变成0
; -
将某一位的
0
变成1
; -
将某两位的
0
和1
交换。
求将原序列变成目标序列的最小操作次数。
题解
发现第 3 3 3 种操作在合法的情况下一定是比进行 2 2 2 次操作 1 , 2 1,2 1,2 更优的。
于是我们让操作 3 3 3 尽可能多。
每一对 1 , 2 1,2 1,2 都可以转化为 1 1 1 次操作 3 3 3,所以分别统计操作 1 , 2 1,2 1,2 进行的次数 x , y x,y x,y,则操作 3 3 3 最多进行 min ( x , y ) \min(x,y) min(x,y) 次。
最小花费即为:
-
操作 1 1 1: x − min ( x , y ) x-\min(x,y) x−min(x,y) 次;
-
操作 2 2 2: y − min ( x , y ) y-\min(x,y) y−min(x,y) 次;
-
操作 3 3 3: min ( x , y ) \min(x,y) min(x,y) 次。
答案为 x + y − min ( x , y ) x+y-\min(x,y) x+y−min(x,y)。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#define int long long
using namespace std;
const int N = 200010;
int T, n, k, x;
int a[N], b[N];
signed main()
{
cin >> T;
while (T -- )
{
int c10 = 0, c01 = 0, res = 0;
cin >> n;
for (int i = 1; i <= n; i ++ ) scanf("%1lld", &a[i]);
for (int i = 1; i <= n; i ++ ) scanf("%1lld", &b[i]);
for (int i = 1; i <= n; i ++ )
{
if (a[i] == 1 && b[i] == 0) c10 ++ ;
if (a[i] == 0 && b[i] == 1) c01 ++ ;
}
res = c10 + c01 - min(c10, c01);
printf("%lld\n", res);
}
}