#define ll long longvoid solve() {
int _;
cin >> _;
vector<vector<int>> tree(2e5 * 2), next(2e5 * 2);
vector<int> end(2e5 * 2);
for (auto& i: tree) i.resize(20, 0);
for (auto& i: next) i.resize(2, 0);
for (int tc = 0; tc < _; ++tc) {
int n, k;
cin >> n >> k;
vector<int> p(n), q(k), cache(k);
for (auto& i: p) cin >> i;
for (auto& i: q) cin >> i;
int root, tail = 0;
auto build = [&] {
for (int i = 0; i < 20; ++i) tree[tail][i] = 0;
next[tail][0] = next[tail][1] = -1;
end[tail] = 0;
assert(tail < tree.size());
return tail++;
};
root = build();
auto move = [&](const int x, const int v) {
int i = 20;
while (i >= 0 && (x & 1 << i) == 0) --i;
int cur = root;
while (i >= 0) {
const int flag = x & 1 << i ? 1 : 0;
if (next[cur][flag] == -1) next[cur][flag] = build();
cur = next[cur][flag];
tree[cur][i] += v;
--i;
}
end[cur] += v;
};
for (const auto& pi: p) move(pi, 1);
ll ans = 0;
constexpr ll mod = 998244353;
auto pos = [&](const int gap, const int cnt) {
if (gap >= k) return;
const ll ps = 1ll * (k - gap + 1) * (k - gap) / 2 % mod;
const ll tmp = ps * cnt % mod;
ans = (ans + tmp) % mod;
};
auto neg = [&](int gap, const int cnt) {
gap += 1;
if (gap > k) return;
const ll ps = 1ll * (k - gap + 1) * (k - gap) / 2 % mod;
const ll all = 1ll * (k + 1) * k / 2 % mod;
const ll tmp = (all - ps - k) * cnt % mod;
ans = (ans + tmp) % mod;
};
for (const auto& pi: p) {
move(pi, -1);
int i = 20;
while (i >= 0 && (pi & 1 << i) == 0) --i;
int cur = root;
while (i >= 0) {
const int flag = pi & 1 << i ? 1 : 0;
if (const int other = next[cur][flag ^ 1]; other != -1)
for (int ind = 0; ind < 20; ++ind)
if (tree[other][ind] > 0) {
const int gap = ind + (flag ^ 1) - i;
pos(max(0, gap), tree[other][ind]);
if (gap < 0) neg(-gap, tree[other][ind]);
}
cur = next[cur][flag];
const int gap = max(-i, -k + 1);
pos(max(0, gap), end[cur]);
if (gap < 0) neg(-gap, end[cur]);
--i;
}
auto cal = [&](const int node) {
if (node == -1) return;
for (int ind = 0; ind < 20; ++ind)
if (tree[node][ind] > 0) {
const int gap = ind + 2;
pos(max(0, gap), tree[node][ind]);
if (gap < 0) neg(-gap, tree[node][ind]);
}
};
cal(next[cur][0]);
cal(next[cur][1]);
}
function<ll(vector<int>&, vector<int>&, int, int)> mergeSort = [&](vector<int>& record, vector<int>& tmp, const int l, const int r) {
if (l >= r) return 0ll;
const int mid = (l + r) / 2;
ll inv_count = mergeSort(record, tmp, l, mid) + mergeSort(record, tmp, mid + 1, r);
int i = l, j = mid + 1, poss = l;
while (i <= mid && j <= r) {
if (record[i] <= record[j]) {
tmp[poss] = record[i];
++i;
inv_count += j - (mid + 1);
} else {
tmp[poss] = record[j];
++j;
}
++poss;
}
for (int ind = i; ind <= mid; ++ind) {
tmp[poss++] = record[ind];
inv_count += j - (mid + 1);
}
for (int ind = j; ind <= r; ++ind) {
tmp[poss++] = record[ind];
}
copy(tmp.begin() + l, tmp.begin() + r + 1, record.begin() + l);
return inv_count;
};
const ll cnt = mergeSort(q, cache, 0, k - 1);
const ll tmp = cnt * n % mod;
ans = (ans + tmp) % mod;
cout << ans << endl;
}
}