首页 > 其他分享 >D. Yet Another Inversions Problem

D. Yet Another Inversions Problem

时间:2023-12-26 23:35:24浏览次数:29  
标签:10 le cdot 18 array int Inversions Problem Yet

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:

$a_{i \cdot k+j}=p_i \cdot 2^{q_j}$ for all $0 \le i < n$ and all $0 \le j < k$

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

相关文章

  • 【模版】高精度减法 (A - B problem)
    直接看代码和注释吧qwq高精度就是模拟嘛ww还是python好,自带高精度#include<bits/stdc++.h>#defineMAXN10500usingnamespacestd;stringa,b;//选择字符串。因为字符串储存了每个串的长度,可以直接调用。intna[MAXN],nb[MAXN],ans[MAXN];boolpd;intmain(){......
  • 【模版】高精度乘法 (A*B problem)
    和A+Bproblem类似,不多说,直接看代码和注释就好啦!ww感觉这东西只要有个概念就行了...就是在练模拟?www其他语言似乎有大数加减乘除? 这样的高精度算法时间复杂度O(n2),n是数字位数,如果位数过大还是很慢。可以利用快速傅里叶变换的方式加速高精度乘法。(虽然都是我连傅里叶级数都没学......
  • CodeForces 1909F2 Small Permutation Problem (Hard Version)
    洛谷传送门CF传送门感觉这个题还是挺不错的。考虑F1。考察\(a_i\)差分后的意义,发现\(a_i-a_{i-1}\)就是\((\sum\limits_{j=1}^{i-1}[p_j=i])+p_i\lei\)。考虑将其转化为棋盘问题。在\((i,p_i)\)放一个车,那么\(a_i-a_{i-1}\)就是\((1,i)\sim......
  • kaggle Open Problems – Single-Cell Perturbations 1st & 2nd place solution summa
    Leaderboard:https://www.kaggle.com/competitions/open-problems-single-cell-perturbations/leaderboard2ndSolution:https://www.kaggle.com/competitions/open-problems-single-cell-perturbations/discussion/458738Code:https://github.com/Eliorkalfon/single_ce......
  • A. Problemsolving Log
    原题链接结合样例读题1.输入序列代表每一时刻思考的题目2.如果思考的题目时长超过给定值就代表题目解决。综上如果一个字符的出现次数大于给定值就代表解决了这个问题。代码#include<bits/stdc++.h>usingnamespacestd;intmain(){intt;cin>>t;while(t......
  • CF Edu160E Matrix Problem
    场上疯狂想求任意解+改动解至最优。。想不下去的时候一定要再读一遍题跳出来啊。限制每一行每一列的\(1\)的个数,这很匹配啊!!考虑网络流,左侧\(n\)个节点连流量\(a_i\),右侧\(m\)个节点连流量\(b_i\)。对于原矩阵中为\(0\)的项\((i,j)\),若新矩阵中为\(0\)则流量为\(0......
  • CF Edu160F Palindromic Problem
    赛时过的人少估计是因为难调。考虑修改一个字符的贡献,会使得所有以该字符为瓶颈的回文串增加长度,同时会使得原来所有最长回文串经过该位置的位置减少长度。换个视角,不妨通过二分+哈希分别预处理出以每个位置为回文中心的最长回文串长度、以及修改一个字符后的最长回文串长度,则对......
  • CF1446D Frequency Problem
    题意给定\(n\)个数。求最长的子段使得子段内有两个众数。Sol考虑全局众数对于子段的众数的影响。注意到对于答案有贡献的子段一定包含全局众数,读者自证不难。考虑对于每个数出现的次数根号分治。对于出现次数大于根号的数:种类不超过根号。考虑暴力对于每一种数,考虑她成......
  • CF1913 E Matrix Problem 题解
    LinkCF1913EMatrixProblemQuestion给定一个\(n\timesm\)的01矩阵,你可以把矩阵中的任意一个元素01翻转需要最后的矩阵满足,每行\(1\)的个数有\(A[i]\)个,每列\(1\)的个数有\(B[i]\)个Solution这貌似是一道非常经典的费用流题目我们建立\(n\)个行节点,\(m......
  • [ABC318G] Typical Path Problem 题解
    原题链接:ABC318G显然是圆方树。点双缩点过后建立一颗以点\(c\)为根节点的圆方树,考虑什么情况是合法的。从点\(a\)开始往上跳直到跳到点\(c\),如果中间走过了某一个方点并且这个方点与\(b\)点有直接连边,那么就是合法的;否则不合法。证明:如果路径中所经过的方点和\(b\)点......