F. Unjust Binary Life

F. Unjust Binary Life

Yuri is given two binary strings $a$ and $b$, both of which are of length $n$. The two strings dynamically define an $n \times n$ grid. Let $(i, j)$ denote the cell in the $i$-th row and $j$-th column. The initial value of cell $(i, j)$ has the value of $a_i \oplus b_j$, where $\oplus$ denotes the bitwise XOR operation. .

Yuri's journey always starts at cell $(1, 1)$. From a cell $(i, j)$, she can only move down to $(i + 1, j)$ or right to $(i, j + 1)$. Her journey is possible if there exists a valid path such that all cells on the path, including $(1, 1)$, have a value of 0.

Before her departure, she can do the following operation for any number of times:

  • Choose one index $1 \le i \le n$, and flip the value of either $a_i$ or $b_i$ ($0$ becomes $1$, and $1$ becomes $0$). The grid will also change accordingly.

Let $f(x, y)$ denote the minimum required operations so that Yuri can make her journey to the cell $(x,y)$. You must determine the sum of $f(x, y)$ over all $1 \leq x, y \leq n$.

Note that each of these $n^2$ cases is independent, meaning you need to assume the grid is in its original state in each case (i.e., no actual operations are performed).

Input

Each test contains multiple test cases. The first line contains the number of test cases $t$ ($1 \le t \le 10^4$). The description of the test cases follows.

The first line of each test case contains one integer $n$ ($1 \le n \le 2 \cdot 10^5$).

The second line of each test case contains a binary string $a$ ($|a| = n$, $a_i \in \{0, 1\}$).

The third line of each test case contains a binary string $b$ ($|b| = n$, $b_i \in \{0, 1\}$).

It is guaranteed that the sum of $n$ over all test cases does not exceed $2 \cdot 10^5$.

Output

For each test case, output one integer — the sum of minimum operations over all possible cells.

Example

Input

3
2
11
00
2
01
01
4
1010
1101

Output

5
4
24

Note

In the first test case, the $2 \times 2$ grid is shown below.

$$ 11 \\ 11 $$

In the initial state, Yuri cannot reach any cell.

Yuri can flip $a_1$ so that the grid becomes:

$$ 00 \\ 11 $$

and Yuri can travel to cells $(1,1)$ and $(1,2)$.

On the other hand, Yuri can flip $b_1$ so that the grid becomes:

$$ 01 \\ 01 $$

and Yuri can travel to cells $(1,1)$ and $(2,1)$.

To move to the cell $(2,2)$, it can be shown that she must perform at least two operations. For example, she can flip both $a_1$ and $a_2$ so that the grid becomes:

$$ 00 \\ 00 $$

Therefore, the answer is $1+1+1+2=5$.

 

解题思路

  为了从 $(1,1)$ 走到 $(x,y)$,需要保证 $a_1, \ldots, a_x$ 与 $b_1 \ldots b_y$ 的值都相等,即 $a_1 = \cdots = a_x = b_1 = \cdots b_y$。可以将从 $(1,1)$ 走到 $(x,y)$ 的过程看作是,初始有指针 $i$ 和 $j$ 分别指向 $a$ 和 $b$ 的第一个元素,每次向右或向下移动一个格子,相当于 $i$ 或 $j$ 向右前进一位。假设当前在位置 $(i,j)$,要保证 $(i,j)$ 的值为 $0$ 就需要满足 $a_i = b_j$。如果要向右移动到 $(i+1,j)$,则必须有 $a_{i+1} = b_j$。同理如果要向下移动到 $(i,j+1),则必须有 $a_i = b_{j+1}$。从而推出 $a_1 = \cdots = a_x = b_1 = \cdots b_y$。

  因此要从 $(1,1)$ 走到 $(x,y)$,就需要将 $a_1, \ldots, a_x$ 与 $b_1 \ldots b_y$ 中的值变成全 $0$ 或者全 $1$,对应的最小操作次数就是这段区间内 $0$ 和 $1$ 的最小个数。定义 $f_0(x)$ 和 $f_1(x)$ 分别表示 $a_1, \ldots, a_x$ 中 $0$ 的个数和 $1$ 的个数,$g_0(y)$ 和 $g_1(y)$ 分别表示 $b_1, \ldots, b_y$ 中 $0$ 的个数和 $1$ 的个数。那么从 $(1,1)$ 走到 $(x,y)$ 的最小操作次数就是 $\min\{ f_0(x) + g_0(y), f_1(x) + g_1(y) \}$,要求的最终答案就是 $\sum\limits_{x=1}^{n}{\sum\limits_{y=1}^{n}{\min\{ f_0(x) + g_0(y), f_1(x) + g_1(y) \}}}$。

  要求解上述答案,我们可以枚举 $x$,在 $x$ 固定的情况下求所有 $y$ 对答案的贡献。在 $x$ 固定时考虑在什么情况下取 $\min\{ f_0(x) + g_0(y), f_1(x) + g_1(y) \} = f_0(x) + g_0(y)$,此时有 $f_0(x) + g_0(y) \leq f_1(x) + g_1(y) \Rightarrow g_0(y) - g_1(y) \leq f_1(x) - f_0(x)$。相应地,当 $g_0(y) - g_1(y) > f_1(x) - f_0(x)$ 时,取 $\min\{ f_0(x) + g_0(y), f_1(x) + g_1(y) \} = f_1(x) + g_1(y)$。这个问题类似于有序数组中差绝对值之和,只不过把绝对值变成了最小值。

  在本题中,做法是在枚举 $x$ 前先对 $g$ 以 $g_0(y) - g_1(y)$ 为关键字进行升序排序,并对排序后的结果预处理出 $s_0(y) = \sum\limits_{i=1}^{y}{g_0(i)}$ 和 $s_1(y) = \sum\limits_{i=1}^{y}{g_1(i)}$,然后对于确定的 $x$ 先通过二分在 $g$ 中找到满足 $g_0(y) - g_1(y) \leq f_1(x) - f_0(x)$ 的最大下标 $m$(若不存在这样的下标则定义 $m=0$,并规定 $g_0(0)=g_1(0)=0$),最后 $\sum\limits_{y=1}^{n}{\min\{ f_0(x) + g_0(y), f_1(x) + g_1(y) \}}$ 的结果就是 $\sum\limits_{y=1}^{m}{f_0(x)+g_0(y)} + \sum\limits_{y=m+1}^{n}{f_1(x)+g_1(y)} = \left( m \times f_0(x) + s_0(m) \right) + \left( (n-m) \times f_1(x) + s_1(n) - s_1(m) \right)$。

  AC 代码如下,时间复杂度为 $O(n \log{n})$:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 2e5 + 5;

char a[N], b[N];
int f[2][N], g[2][N], p[N];
LL s[2][N];

void solve() {
    int n;
    cin >> n >> a >> b;
    for (int i = 0; i < n; i++) {
        f[0][i + 1] = f[0][i] + (a[i] == '0');
        f[1][i + 1] = f[1][i] + (a[i] == '1');
        g[0][i + 1] = g[0][i] + (b[i] == '0');
        g[1][i + 1] = g[1][i] + (b[i] == '1');
    }
    iota(p + 1, p + n + 1, 1);
    sort(p + 1, p + n + 1, [&](int i, int j) {
        return g[0][i] - g[1][i] < g[0][j] - g[1][j];
    });
    for (int i = 1; i <= n; i++) {
        s[0][i] = s[0][i - 1] + g[0][p[i]];
        s[1][i] = s[1][i - 1] + g[1][p[i]];
    }
    LL ret = 0;
    for (int i = 1; i <= n; i++) {
        int l = 0, r = n;
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (g[0][p[mid]] - g[1][p[mid]] <= f[1][i] - f[0][i]) l = mid;
            else r = mid - 1;
        }
        ret += 1ll * l * f[0][i] + s[0][l] + LL(n - l) * f[1][i] + s[1][n] - s[1][l];
    }
    cout << ret << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    
    return 0;
}

  在推出 $\sum\limits_{x=1}^{n}{\sum\limits_{y=1}^{n}{\min\{ f_0(x) + g_0(y), f_1(x) + g_1(y) \}}}$ 后,官方题解给出的做法是将 $\min$ 的式子转成绝对值表示,不是很懂动机是什么。首先有结论 $\min\{a,b\} = \frac{a+b}{2} - \frac{|a-b|}{2}$,可以通过分类讨论来证明其成立,实际上光是这个结论就已经不知道了。所以有 $$\begin{align*} &\sum\limits_{x = 1}^{n}{\sum\limits_{y = 1}^{n}{\min\{ f_0(x) + g_0(y), f_1(x) + g_1(y) \}}} \\ = &\sum\limits_{x = 1}^{n}{\sum\limits_{y = 1}^{n}{\frac{f_0(x) + g_0(y) + f_1(x) + g_1(y)}{2} - \frac{|f_0(x) + g_0(y) - (f_1(x) + g_1(y))|}{2}}} \\ = &\sum\limits_{x = 1}^{n}{\sum\limits_{y = 1}^{n}{\frac{f_0(x) + g_0(y) + f_1(x) + g_1(y)}{2}}} - \sum\limits_{x = 1}^{n}{\sum\limits_{y = 1}^{n}{\frac{|f_0(x) + g_0(y) - (f_1(x) + g_1(y))|}{2}}} \\ = &\frac{1}{2}\sum\limits_{x = 1}^{n}{\sum\limits_{y = 1}^{n}{x+y}} - \frac{1}{2}\sum\limits_{x = 1}^{n}{\sum\limits_{y = 1}^{n}{|g_0(y) - g_1(y) - (f_1(x) - f_0(x))|}} \\ = &\frac{n^2(n+1)}{2} - \frac{1}{2}\sum\limits_{x = 1}^{n}{\sum\limits_{y = 1}^{n}{|g_0(y) - g_1(y) - (f_1(x) - f_0(x))|}} \\ \end{align*}$$

  剩下的问题就是如何求解 $\sum\limits_{x = 1}^{n}{\sum\limits_{y = 1}^{n}{|g_0(y) - g_1(y) - (f_1(x) - f_0(x))|}}$ ,与上述的方法几乎一样,不同的地方在于确定了 $x$ 后,$\sum\limits_{y = 1}^{n}{|g_0(y) - g_1(y) - (f_1(x) - f_0(x))|}$ 的结果为 $\sum\limits_{y=1}^{m}{f_1(x) - f_0(x) - (g_0(y) - g_1(y))} + \sum\limits_{y=m+1}^{n}{g_0(y) - g_1(y) - (f_1(x) - f_0(x)) = \left( m \times (f_1(x) - f_0(x)) - s(m) \right) + \left( s(n) - s(m) + (n-m) \times (f_1(x) - f_0(x)) \right)}$,其中定义 $s(y) = \sum\limits_{i=1}^{y}{g_0(i) - g_1(i)}$。

  AC 代码如下,时间复杂度为 $O(n \log{n})$:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 2e5 + 5;

char a[N], b[N];
int f[2][N], g[2][N], p[N];
LL s[N];

void solve() {
    int n;
    cin >> n >> a >> b;
    for (int i = 0; i < n; i++) {
        f[0][i + 1] = f[0][i] + (a[i] == '0');
        f[1][i + 1] = f[1][i] + (a[i] == '1');
        g[0][i + 1] = g[0][i] + (b[i] == '0');
        g[1][i + 1] = g[1][i] + (b[i] == '1');
    }
    iota(p + 1, p + n + 1, 1);
    sort(p + 1, p + n + 1, [&](int i, int j) {
        return g[0][i] - g[1][i] < g[0][j] - g[1][j];
    });
    for (int i = 1; i <= n; i++) {
        s[i] = s[i - 1] + g[0][p[i]] - g[1][p[i]];
    }
    LL ret = 0;
    for (int i = 1; i <= n; i++) {
        int l = 0, r = n;
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (g[0][p[mid]] - g[1][p[mid]] <= f[1][i] - f[0][i]) l = mid;
            else r = mid - 1;
        }
        ret += l * LL(f[1][i] - f[0][i]) - s[l] + s[n] - s[l] - LL(n - l) * (f[1][i] - f[0][i]);
    }
    ret = 1ll * n * n * (n + 1) / 2 - ret / 2; 
    cout << ret << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    
    return 0;
}

 

参考资料

  Codeforces Round 1042 | maspyのHP:https://maspypy.com/codeforces-round-1042

  Codeforces Round 1042 (Div. 3) Editorial:https://codeforces.com/blog/entry/145439

posted @ 2025-08-12 12:33  onlyblues  阅读(137)  评论(0)    收藏  举报
Web Analytics