D. Yet Another Inversions Problem
You are given a permutation $p_0, p_1, \ldots, p_{n-1}$ of odd integers from $1$ to $2n-1$ and a permutation $q_0, q_1, \ldots, q_{k-1}$ of integers from $0$ to $k-1$.
An array $a_0, a_1, \ldots, a_{nk-1}$ of length $nk$ is defined as follows:
For example, if $p = [3, 5, 1]$ and $q = [0, 1]$, then $a = [3, 6, 5, 10, 1, 2]$.
Note that all arrays in the statement are zero-indexed. Note that each element of the array $a$ is uniquely determined.
Find the number of inversions in the array $a$. Since this number can be very large, you should find only its remainder modulo $998\,244\,353$.
An inversion in array $a$ is a pair $(i, j)$ ($0 \le i < j < nk$) such that $a_i > a_j$.
Input
The first line contains a single integer $t$ ($1 \le t \le 10^4$) — the number of test cases.
The first line of each test case contains two integers $n$ and $k$ ($1 \le n, k \le 2 \cdot 10^5$) — the lengths of arrays $p$ and $q$.
The second line of each test case contains $n$ distinct integers $p_0, p_1, \ldots, p_{n-1}$ ($1 \le p_i \le 2n-1$, $p_i$ is odd) — the array $p$.
The third line of each test case contains $k$ distinct integers $q_0, q_1, \ldots, q_{k-1}$ ($0 \le q_i < k$) — the array $q$.
It is guaranteed that the sum of $n$ over all test cases doesn't exceed $2 \cdot 10^5$ and the sum of $k$ over all test cases doesn't exceed $2 \cdot 10^5$.
Output
For each test case, output one integer: the number of inversions in array $a$ modulo $998\,244\,353$.
Example
Input
4
3 2
3 5 1
0 1
3 4
1 3 5
3 2 0 1
1 5
1
0 1 2 3 4
8 3
5 1 7 11 15 3 9 13
2 0 1
Output
9
25
0
104
Note
In the first test case, array $a$ is equal to $[3, 6, 5, 10, 1, 2]$. There are $9$ inversions in it: $(0, 4)$, $(0, 5)$, $(1, 2)$, $(1, 4)$, $(1, 5)$, $(2, 4)$, $(2, 5)$, $(3, 4)$, $(3, 5)$. Note that these are pairs $(i, j)$ such that $i < j$ and $a_i > a_j$.
In the second test case, array $a$ is equal to $[8, 4, 1, 2, 24, 12, 3, 6, 40, 20, 5, 10]$. There are $25$ inversions in it.
In the third test case, array $a$ is equal to $[1, 2, 4, 8, 16]$. There are no inversions in it.
解题思路
题解给出的做法挺麻烦的,这里提供另外一种思路。
把题目描述的长度为 $nk$ 的序列 $a$ 看作是一个 $n \times k$ 的矩阵 $A$,则有 $A_{i,j} = p_i \cdot 2^{q_j}$。另外 $a_i$ 对应于 $A_{x,y}$,其中 $(x,y)$ 等于 $(\lfloor \frac{i}{n} \rfloor, i \bmod k)$。
求序列的逆序对个数的做法是枚举每一个元素 $a_i$ 并统计 $a_j, \, j \in [0, i-1]$ 中比 $a_i$ 严格大的元素数量。对应到矩阵中就是枚举每一个元素 $A_{x,y}$(下图红色部分),分别统计 $A_{x,j}, \, j \in [0, y-1]$(下图橙色部分)和 $A_{i,j}, \, \left\{ (i,j) \mid 0 \leq i \leq x-1, \, 0 \leq j < k \right\}$(下图绿色部分)中比 $A_{x,y}$ 严格大的元素数量。
首先橙色部分很容易统计,只需求序列 $q$ 的某个前缀的逆序对数量即可。定义 $f(0,i)$ 表示 $q_0 \sim q_i$ 的逆序对的数量,因此所有 $A_{x,y}$ 的橙色部分的逆序对总数就是 $n \times \sum\limits_{i=0}^{k-1}{f(0,i)}$,可以用树状数组求逆序对的做法以 $O(k \log{k})$ 的时间复杂度求出来。
考虑绿色的部分。首先注意到每个值都是 $p_i \cdot 2^{q_j}$ 的形式,而 $p_i$ 最大只有 $4 \cdot 10^5 \mathrm{-} 1$,意味着对于另外一个值 $p_{i'} \cdot 2^{q_{j'}}$,如果 $q_{j'} - q_{j} > 18$ 则必然有 $p_{i'} \cdot 2^{q_{j'}} > p_i \cdot 2^{q_j}$,因为 $2^{19} > 4 \cdot 10^5$。所以对于 $A_{x,y}$,我们只需考虑枚举绿色部分中 $q_j$ 在范围 $[q_y - 18, q_y + 18]$ 的列中的元素,统计比 $A_{x,y}$ 大的元素数量即可。对于 $q_j > q_y + 18$ 的部分,这些列的元素必定比 $A_{x,y}$ 大,总的数量是 $(m - 1 - (q_y + 18)) \times x$。对于 $q_j < q_y - 18$ 的部分,这些列的元素必定比 $A_{x,y}$ 小,不用统计。
因此很朴素的思想是先考虑某一行 $x$,然后依次枚举 $y$,找到 $q_j$ 在 $[q_y - 18, q_y + 18]$ 中的列,对于每一列求序列 $p$ 的前缀 $p_0 \sim p_{x-1}$ 中比 $p_x \cdot 2^{q_y - q_j}$ 大的元素数量(树状数组实现)。再考虑回 $n$ 行,总的时间复杂度就是 $O(nk \log^2{n})$。
实际上并不用枚举 $y$,因为可以发现不管 $y$ 的值是多少,$p_y - p_j$ 总是在区间 $[-18, 18]$ 内,因此 $p_x \cdot 2^{q_y - q_j}$ 可能的值不超过 $37$ 个。所以只用考虑在 $1 \sim k-1$ 中有多少个值能使得 $p_x \cdot 2^{q_y - q_j}$ 取到 $p_x \cdot 2^{-18}, \, p_x \cdot 2^{-17}, \, \ldots, \, p_x \cdot 2^{18}$。
首先很明显 $1 \sim k-1$ 中每个值都能得到 $p_x \cdot 2^{0}$。再考虑 $p_x \cdot 2^{1} \sim p_x \cdot 2^{18}$,对于某个 $p_x \cdot 2^{i}$,很明显只有 $v \in [i, k-1]$ 中的数能存在某个 $j \in [0, k-1]$ 使得 $v - j = i$。同理对于 $p_x \cdot 2^{-18} \sim p_x \cdot 2^{-1}$ 中的某个 $p_x \cdot 2^{i}$,只有 $v \in [0, k-1-i]$ 中的数能得到。
另外还要考虑 $1 \sim k-1$ 所有值的大于 $p_x \cdot 2^{18}$ 的部分。对于某个值 $i$,$v \in [i+19, k-1]$ 的值都满足 $v - i > 18$,因此这些元素的总和就是$$\begin{align*} &x \times \sum\limits_{i=0}^{k-1}{\max\{ 0, k-i-19 \}} \\ = \, &x \times \sum\limits_{i=0}^{k-19}{k-i-19} \end{align*}$$
定义 $g(i, j)$ 表示 $p_0 \sim p_i$ 中严格大于 $j$ 的元素数量,因此某一行 $x$ 的所有的 $y$ 在绿色部分中的逆序对数量就是$$x \times \sum\limits_{i=0}^{k-19}{m-i-19} \; + \; m \cdot g(x-1, p_x) \; + \; \sum\limits_{i=1}^{18}{(k - i) \cdot \left(g(x-1, p_x \cdot 2^i) + g(x-1, p_x \cdot 2^{-i})\right)}$$
AC 代码如下,时间复杂度为 $O(n \log^2{n})$:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10, mod = 998244353;
int n, m, k;
int p[N], q[N];
int tr[N * 2];
int lowbit(int x) {
return x & -x;
}
void add(int x) {
for (int i = x; i <= k; i += lowbit(i)) {
tr[i]++;
}
}
int query(int x) {
int ret = 0;
for (int i = x; i; i -= lowbit(i)) {
ret += tr[i];
}
return ret;
}
void solve() {
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i++) {
scanf("%d", p + i);
}
for (int i = 0; i < m; i++) {
scanf("%d", q + i);
}
k = max(2 * n - 1, m);
int ret = 0;
memset(tr, 0, k + 10 << 2);
for (int i = 0; i < m; i++) {
ret = (ret + i - query(q[i] + 1)) % mod;
add(q[i] + 1);
}
ret = 1ll * ret * n % mod;
memset(tr, 0, k + 10 << 2);
for (int i = 0; i < n; i++) {
if (m > 18) ret = (ret + (m - 18ll) * (m - 19) / 2 % mod * i) % mod;
ret = (ret + 1ll * (i - query(p[i])) * m) % mod;
for (int j = 1; j <= 18 && j < m; j++) {
ret = (ret + 1ll * (i - query(min((LL)k, (LL)p[i] << j))) * (m - j)) % mod;
ret = (ret + 1ll * (i - query(p[i] >> j)) * (m - j)) % mod;
}
add(p[i]);
}
printf("%d\n", ret);
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
参考资料
Editorial of Codeforces Round 917 (Div. 2):https://codeforces.com/blog/entry/123721
Codeforces Round 917 (Div. 2) A - F:https://zhuanlan.zhihu.com/p/673963234
标签:10,le,cdot,18,array,int,Inversions,Problem,Yet From: https://www.cnblogs.com/onlyblues/p/17928855.html