看到区间端点是
109
10
9
级别的,果断离散化。
然后把所有区间按照离散化之前的长度从小到大排序。
考虑如果在排序后连续的一段中选出
M
M
个区间,那么如何判断是否存在一个合法方案呢?
线段树!
即维护一个序列,一开始全部为。
然后对每个区间进行这样一个处理:对每个区间
[l,r]
[
l
,
r
]
,把序列的
[l,r]
[
l
,
r
]
范围内的所有数都加上
1
1
。
处理完毕后,如果整个序列的最大值,那么有解。
又由于要求最小代价,因此考虑尺取法:
维护两个指针
L,R
L
,
R
,表示当前方案下选取的区间是从第
L
L
个区间到第个区间。并且这个选取方案是合法的。
每次把右指针
R
R
右移一个单位之后,也要相应地右移,具体是:
如果把第
L
L
个区间去掉就不存在合法方案(把所有区间加入都无法让序列的最大值),
L
L
就不再右移,否则不断右移,直到不能再右移为止。
期间用线段树维护序列,并且不断地用第个区间的长度
−
−
第个区间的长度更新答案。
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define p2 p << 1
#define p3 p << 1 | 1
using namespace std;
inline int read()
{
int res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
return bo ? ~res + 1 : res;
}
typedef long long ll;
const int N = 5e5 + 5, M = N << 1, L = N << 3;
struct cyx
{
int l, r, xl, xr, len;
} a[N];
ll ans = 1ll << 62;
inline bool comp(const cyx &a, const cyx &b)
{
return a.len < b.len;
}
int n, m, tm, orz[M], T[L], add[L];
void down(int p)
{
add[p2] += add[p];
add[p3] += add[p];
add[p] = 0;
}
void upt(int p)
{
T[p] = max(T[p2] + add[p2], T[p3] + add[p3]);
}
void change(int l, int r, int s, int e, int v, int p)
{
if (l == s && r == e) return (void) (add[p] += v);
int mid = l + r >> 1;
down(p);
if (e <= mid) change(l, mid, s, e, v, p2);
else if (s >= mid + 1) change(mid + 1, r, s, e, v, p3);
else change(l, mid, s, mid, v, p2),
change(mid + 1, r, mid + 1, e, v, p3);
upt(p);
}
int main()
{
n = read(); m = read();
for (int i = 1; i <= n; i++)
{
a[i].xl = read(); a[i].xr = read();
a[i].len = a[i].xr - a[i].xl;
orz[(i << 1) - 1] = a[i].xl, orz[i << 1] = a[i].xr;
}
sort(orz + 1, orz + (n << 1) + 1);
tm = unique(orz + 1, orz + (n << 1) + 1) - orz - 1;
for (int i = 1; i <= n; i++)
{
a[i].l = lower_bound(orz + 1, orz + tm + 1, a[i].xl) - orz;
a[i].r = lower_bound(orz + 1, orz + tm + 1, a[i].xr) - orz;
}
sort(a + 1, a + n + 1, comp);
for (int r = 1, l = 1; r <= n; r++)
{
change(1, n << 1, a[r].l, a[r].r, 1, 1);
while (l < r && T[1] + add[1] >= m)
change(1, n << 1, a[l].l, a[l].r, -1, 1), l++;
if (l > 1 && T[1] + add[1] < m)
change(1, n << 1, a[l - 1].l, a[l - 1].r, 1, 1), l--;
if (T[1] + add[1] >= m)
ans = min(ans, 1ll * (a[r].len - a[l].len));
}
if (ans == (1ll << 62)) puts("-1");
else cout << ans << endl;
return 0;
}