D2. Dances (Hard Version)
D2. Dances (Hard Version)
This is the hard version of the problem. The only difference is that in this version $m \leq 10^9$.
You are given two arrays of integers $a_1, a_2, \ldots, a_n$ and $b_1, b_2, \ldots, b_n$. Before applying any operations, you can reorder the elements of each array as you wish. Then, in one operation, you will perform both of the following actions, if the arrays are not empty:
- Choose any element from array $a$ and remove it (all remaining elements are shifted to a new array $a$),
- Choose any element from array $b$ and remove it (all remaining elements are shifted to a new array $b$).
Let $k$ be the final size of both arrays. You need to find the minimum number of operations required to satisfy $a_i < b_i$ for all $1 \leq i \leq k$.
This problem was too easy, so the problem author decided to make it more challenging. You are also given a positive integer $m$. Now, you need to find the sum of answers to the problem for $m$ pairs of arrays $(c[i], b)$, where $1 \leq i \leq m$. Array $c[i]$ is obtained from $a$ as follows:
- $c[i]_1 = i$,
- $c[i]_j = a_j$, for $2 \leq j \leq n$.
Input
Each test consists of multiple test cases. The first line contains a single integer $t$ ($1 \leq t \leq 10^4$) - the number of sets of input data. This is followed by their description.
The first line of each test case contains two integers $n$ and $m$ ($2 \leq n \leq 10^5$, $1 \leq m \leq 10^9$) - the size of arrays $a$ and $b$ and the constraints on the value of element $a_1$.
The second line of each test case contains $n - 1$ integers $a_2, \ldots, a_n$ ($1 \leq a_i \leq 10^9$).
The third line of each test case contains $n$ integers $b_1, b_2, \ldots, b_n$ ($1 \leq b_i \leq 10^9$).
It is guaranteed that the sum of $n$ over all test cases does not exceed $10^5$.
Output
For each test case, output the total number of minimum operations for all pairs of arrays $(c_i, b)$.
Example
input
4
2 4
1
3 2
4 7
5 1 5
3 8 3 3
8 4
4 3 3 2 2 1 1
1 1 1 1 3 3 3 3
9 1
9 2 8 3 7 4 6 5
1 2 3 2 1 4 5 6 5
output
2
12
16
4
Note
In the first test case:
- For the pair of arrays $([1, 1], [3, 2])$, the answer is $0$. No operations or reordering of elements are needed.
- For the pair of arrays $([2, 1], [3, 2])$, the answer is $0$. The elements of the first array can be rearranged to obtain $[1, 2)$. No operations are needed.
- For the pair of arrays $([3, 1], [3, 2])$, the answer is $1$. The element $3$ can be removed from the first array and the element $2$ can be removed from the second array.
- For the pair of arrays $([4, 1], [3, 2])$, the answer is $1$. The element $4$ can be removed from the first array and the element $3$ can be removed from the second array.
解题思路
先解决 D1. Dances (Easy version),此时有 $a_1 = 1$。容易知道答案具有二段性,因此可以二分出最小的删除次数。如果当前要求删除 $k$ 次,那么应该分别将 $a$ 和 $b$ 的哪 $k$ 个元素删除使得剩余的元素满足 $a_i < b_i$ 呢?首先将数组 $a$ 和 $b$ 从小到大排序,由于最后要满足 $a_i < b_i$,因此容易贪心地想到 $a$ 中应该保留尽可能小的数,$b$ 中保留尽可能大的数。所以应该删除 $a$ 的后 $k$ 个元素,删除 $b$ 的前 $k$ 个元素,最后再从左往右依次检查剩余的每对元素是否满足条件即可。时间复杂度为 $O(n \log{n})$。
证明比较简单,这里只证 $a$ 数组,$b$ 数组同理。假设某个最优方案中不是删除后 $k$ 个数,意味着后 $k$ 个元素中必然有一个没被删除,假设为 $a_i$,相对应的,前 $n-k$ 个元素中必然有一个被删除,假设为 $a_j$。由于满足条件,此时有 $a_i < b_i$,$a_j < b_j$,如果我们改成删除 $a_i$ 而保留 $a_j$,那么这个条件还是满足的,相当于 $a_j$ 之后的元素都右移一个单位与 $b$ 比较,而这些位置的 $a$ 都变小了。
考虑 $a_1 = 1 \sim m$ 的情况,定义 $f(i)$ 表示 $a_1 = i$ 时最小的删除次数。由上面贪心的思想知道,当 $a_1 = 1$ 时,$f(1)$ 一定是 $f(i)$ 中最小的。然后题解直接来了句显然存在某个 $x$ 使得 $f(1) = f(2) = \cdots = f(x) = f(x + 1) - 1 = f(x + 2) - 1 = \cdots = f(\inf) - 1$,改变 $a$ 中的一个元素最多会使得答案加 $1$。要是真那么显然比赛时早想出来了...
我按照题解的提示大概推了下,以 $n=6$,$f(1) = 2$ 为例。假设 $a_1$ 在变大的过程中没有出现 $a_i \geq b_i$ 的情况:
那么就会有 $f(1) = f(2) = \cdots f(\inf)$。
而如果 $a_1$ 在变大的过程出现某个 $a_i \geq b_i$,那么就要进行一次删除操作(删除 $a$ 中剩余的最大元素,$b$ 中的最小元素)。删除一次后必然再次满足条件:
所以必然存在某个 $x$,满足 $f(x), \, f(x+1), \, \ldots$ 都比 $f(1)$ 多 $1$,且只能多 $1$。
可以发现 $x$ 也满足二段性,因此可以二分出来。二分出 $\text{mid}$ 后令 $a_1 = \text{mid}$,然后用求 $f(1)$ 的方法求 $f(\text{mid})$ 即可。最后答案就是 $(x-1) \cdot f(1) + (m - x + 1) \cdot (f(1) + 1)$。
这里解释一下为什么二分的边界设为 $m+1$,这是因为在 $1 \sim m$ 中可能不存在分界点 $x$,如果不存在的话最后二分的结果是 $m+1$(否则就是 $x$),上面计算答案的式子仍然成立。
AC 代码如下,时间复杂度为 $O(\log{m} \cdot (n \log{n}))$:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int n, m;
int a[N], b[N], c[N];
bool check(int mid) {
for (int i = 0; i < n - mid; i++) {
if (c[i] >= b[i + mid]) return false;
}
return true;
}
int get(int x) {
memcpy(c, a, n + 10 << 2);
c[0] = x;
sort(c, c + n);
int l = 0, r = n;
while (l < r) {
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
void solve() {
scanf("%d %d", &n, &m);
for (int i = 1; i < n; i++) {
scanf("%d", a + i);
}
for (int i = 0; i < n; i++) {
scanf("%d", b + i);
}
a[0] = 1;
sort(a, a + n);
sort(b, b + n);
int ret = get(1);
int l = 1, r = m + 1;
while (l < r) {
int mid = l + r >> 1;
if (get(mid) > ret) r = mid;
else l = mid + 1;
}
printf("%lld\n", (l - 1ll) * ret + (m - l + 1ll) * (ret + 1));
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
参考资料
Codeforces Round #904 (Div. 2) Editorial:https://codeforces.com/blog/entry/121618
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17783795.html