尺取法吼题哇
先将 \(l,r\) 离散化,然后按照区间长度排序成单调不下降的,然后跟着尺取法的套路来搞,线段树维护就行了。
顺便提一句,开始我没有发现线段树要维护的区间范围可能是 \([1,2N]\) 只开了 \(4\) 倍的空间,结果 \(RE\) 到死。实际上要开 \(8\) 倍,我真菜
#include <iostream>
#include <cstdio>
#include <algorithm>
const int max_n = 500000 + 5;
const int inf = 0x7f7f7f7f;
struct Ask
{
int l, r, len;
}P[max_n];
int N, M, Ans = inf, Tot;
int A[max_n << 1], maxv[max_n << 3], lazy[max_n << 3];
inline int read()
{
register int x = 0;
register char ch = getchar();
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch))
{
x = (x << 1) + (x << 3) + ch - '0';
ch = getchar();
}
return x;
}
void update(int o, int l, int r, int ql, int qr, int v)
{
if(ql <= l && r <= qr)
{
maxv[o] += v;
lazy[o] += v;
return;
}
if(lazy[o])
{
lazy[o << 1] += lazy[o];
lazy[o << 1 | 1] += lazy[o];
maxv[o << 1] += lazy[o];
maxv[o << 1 | 1] += lazy[o];
lazy[o] = 0;
}
int mid = l + r >> 1;
if(ql <= mid) update(o << 1, l, mid, ql, qr, v);
if(mid < qr) update(o << 1 | 1, mid + 1, r, ql, qr, v);
maxv[o] = std::max(maxv[o << 1], maxv[o << 1 | 1]);
}
bool cmp(Ask x, Ask y)
{
return (x.len < y.len);
}
int main()
{
N = read();
M = read();
for(int i = 1; i <= N; ++i)
{
A[i] = P[i].l = read();
A[i + N] = P[i].r = read();
P[i].len = P[i].r - P[i].l;
}
std::sort(&A[1], &A[N << 1 | 1]);
std::sort(&P[1], &P[N + 1], cmp);
Tot = std::unique(&A[1], &A[N << 1 | 1]) - &A[1];
for(int i = 1; i <= N; ++i)
{
P[i].l = std::lower_bound(&A[1], &A[Tot + 1], P[i].l) - &A[0], P[i].r = std::lower_bound(&A[1], &A[Tot + 1], P[i].r) - &A[0];
}
for(int l = 1, r = 0; ; )
{
while(r < N && maxv[1] < M)
{
++r;
update(1, 1, Tot, P[r].l, P[r].r, 1);
}
if(maxv[1] < M) break;
Ans = std::min(Ans, P[r].len - P[l].len);
update(1, 1, Tot, P[l].l, P[l].r, -1);
++l;
}
printf("%d\n", (Ans == inf) ? -1 : Ans);
return 0;
}