【题目链接】
【思路要点】
- 将区间按照长度排序,一系列区间\([l_x,r_x],[l_{x+1},r_{x+1}]...[l_y,r_y]\)中可以选出一组合法的解当且仅当被这些覆盖次数最多的点被覆盖了至少\(M\)次。
- 我们希望使得\(x\)和\(y\)尽可能接近,不难发现,\(y\)是关于\(x\)单调的,因此可以使用Two Pointers求出每一个\(x\)对应的最近的\(y\)。
- 判断是否有点被覆盖了\(M\)次可以使用支持区间加、询问全局最大值的线段树来实现。
- 时间复杂度\(O(NLogN)\)。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 1000005; const int MAXP = 2000005; const int INF = 1e9 + 10; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } struct SegmentTree { struct Node { int lc, rc; int tag, Max; } a[MAXP]; int root, size, n; void build(int &root, int l, int r) { root = ++size; if (l == r) return; int mid = (l + r) / 2; build(a[root].lc, l, mid); build(a[root].rc, mid + 1, r); } void init(int x) { n = x; root = size = 0; build(root, 1, n); } void update(int root) { a[root].Max = max(a[a[root].lc].Max, a[a[root].rc].Max); } void pushdown(int root) { if (a[root].tag == 0) return; int tmp = a[root].lc; a[tmp].Max += a[root].tag; a[tmp].tag += a[root].tag; tmp = a[root].rc; a[tmp].Max += a[root].tag; a[tmp].tag += a[root].tag; a[root].tag = 0; } void modify(int root, int l, int r, int ql, int qr, int d) { if (l == ql && r == qr) { a[root].tag += d; a[root].Max += d; return; } pushdown(root); int mid = (l + r) / 2; if (mid >= ql) modify(a[root].lc, l, mid, ql, min(mid, qr), d); if (mid + 1 <= qr) modify(a[root].rc, mid + 1, r, max(mid + 1, ql), qr, d); update(root); } void modify(int l, int r, int d) { modify(root, 1, n, l, r, d); } int query() { return a[root].Max; } } ST; struct info {int l, r, len; } a[MAXN]; int tmp[MAXN], tot, n, m; bool operator < (info a, info b) { return a.len > b.len; } int main() { read(n), read(m); for (int i = 1; i <= n; i++) { read(a[i].l), read(a[i].r); a[i].len = a[i].r - a[i].l; tmp[++tot] = a[i].l; tmp[++tot] = a[i].r; } sort(a + 1, a + n + 1); sort(tmp + 1, tmp + tot + 1); tot = unique(tmp + 1, tmp + tot + 1) - tmp - 1; ST.init(tot); int last = 1, ans = INF; for (int i = 1; i <= n; i++) { a[i].l = lower_bound(tmp + 1, tmp + tot + 1, a[i].l) - tmp; a[i].r = lower_bound(tmp + 1, tmp + tot + 1, a[i].r) - tmp; ST.modify(a[i].l, a[i].r, 1); while (ST.query() >= m) { chkmin(ans, a[last].len - a[i].len); ST.modify(a[last].l, a[last].r, -1); last++; } } if (ans == INF) writeln(-1); else writeln(ans); return 0; }