$\rm Sol$
法一
可以证明
同理
于是我们可以枚举操作了的前缀
时间复杂度 $\Theta(n).$
法二
容易发现答案满足可二分性
如果选定了答案区间的左端点
于是问题转化成了一个前后缀 $\rm RMQ.$
时间复杂度 $\Theta(n \log n).$
法三
考虑将 $a_i$ 和 $b_i$ 全部取出来排序
于是双指针维护
时间复杂度 $\Theta(n \log n)$
$\rm Code$
#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
int n, m, num, ans = INT_MAX;
pair <int, int> a[N];
bool tag[N];
int idx (int pos) {
return a[pos].second - (a[pos].second <= n ? 0 : n);
}
bool check (int pos) {
if (a[pos].second <= n && num >= m) return false;
if (tag[idx(pos)]) return false;
return true;
}
void del (int pos) {
if (a[pos].second <= n) num++;
tag[idx(pos)] = true;
}
void rev (int pos) {
if (a[pos].second <= n) num--;
tag[idx(pos)] = false;
}
int main () {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n << 1; i++)
scanf("%d", &a[i].first), a[i].second = i;
sort(a + 1, a + 2 * n + 1);
int l = 1, r = 2 * n;
while (check(r)) del(r), r--;
while (r <= n << 1) {
ans = min(ans, a[r].first - a[l].first);
if (a[l].second <= n) while (num >= m && r <= 2 * n) rev(r + 1), r++;
while (tag[idx(l)] && r <= 2 * n) rev(r + 1), r++;
del(l), l++;
}
printf("%d\n", ans);
return 0;
}