Loading

洛谷 P1712 [NOI2016] 区间

很多套路糅合在一起的一道题。

\(len_i = r_i - l_i\)

则所求转化为一个有 \(m\) 个区间的集合 \(S\),满足:

  • 存在一个 \(x\),使得对于所有 \(S\) 中的区间 \(i\),有 \(l_i \le x \le r_i\)
  • \(\max\limits_{i \in S}\{len_i\} - \min\limits_{i \in S}\{len_i\}\) 最小。

对于第二个限制条件,套路地想到按区间长度排序后尺取。

此时时间复杂度为 \(\mathcal{O}(n)\),也就是说,要在 \(\mathcal{O}(\log n)\) 的时间复杂度内进行第一个限制条件的判断。

对于第一个限制条件,\(l_i, r_i \le 10^9\),但 \(n \le 5 \times 10^5\),离散化后即可实现 \(l_i, r_i \le 10^6\)。开一个线段树,维护被覆盖次数最多的点被覆盖的次数,每次只需判断 \(1\) 号结点上的值是否 \(\ge m\) 即可。

时间复杂度 \(\mathcal{O}(n \log n)\)

代码:

#include <bits/stdc++.h>

#define MAXN 500100
#define lson pos << 1
#define rson pos << 1 | 1

using namespace std;

int n, m, tmp[MAXN << 1];

struct Seg {
    int w, lazy;
} t[MAXN << 3];

struct Node {
    int l, r;

    bool operator<(const Node &rhs) const {
        return r - l > rhs.r - rhs.l;
    }
} a[MAXN], b[MAXN];

template<typename _T>
void read(_T &_x) {
    _x = 0;
    _T _f = 1;
    char _ch = getchar();
    while (_ch < '0' || '9' < _ch) {
        if (_ch == '-') _f = -1;
        _ch = getchar();
    }
    while ('0' <= _ch && _ch <= '9') {
        _x = (_x << 3) + (_x << 1) + (_ch & 15);
        _ch = getchar();
    }
    _x *= _f;
}

template<typename _T>
void write(_T _x) {
    if (_x < 0) {
        putchar('-');
        _x = -_x;
    }
    if (_x > 9) write(_x / 10);
    putchar('0' + _x % 10);
}

void pushdown(int pos) {
    if (!t[pos].lazy) return;
    t[lson].w += t[pos].lazy, t[rson].w += t[pos].lazy;
    t[lson].lazy += t[pos].lazy, t[rson].lazy += t[pos].lazy;
    t[pos].lazy = 0;
}

void upd(int pos, int l, int r, int x, int y, int c) {
    if (x <= l && r <= y) {
        t[pos].w += c;
        t[pos].lazy += c;
        return;
    }
    pushdown(pos);
    int mid = (l + r) >> 1;
    if (x <= mid) upd(lson, l, mid, x, y, c);
    if (y > mid) upd(rson, mid + 1, r, x, y, c);
    t[pos].w = max(t[lson].w, t[rson].w);
}

int main() {
    read(n), read(m);
    for (int i = 1; i <= n; i++) {
        read(a[i].l), read(a[i].r);
        tmp[++tmp[0]] = a[i].l, tmp[++tmp[0]] = a[i].r;
    }
    sort(a + 1, a + n + 1);
    sort(tmp + 1, tmp + tmp[0] + 1);
    for (int i = 1; i <= n; i++) {
        b[i].l = lower_bound(tmp + 1, tmp + tmp[0] + 1, a[i].l) - tmp;
        b[i].r = lower_bound(tmp + 1, tmp + tmp[0] + 1, a[i].r) - tmp;
    }
    int l = 1, r = 0, ans = 2e9;
    while (r < n) {
        while (t[1].w < m && r < n) {
            r++;
            upd(1, 1, tmp[0], b[r].l, b[r].r, 1);
        }
        while (t[1].w >= m && l <= r) {
            ans = min(ans, (a[l].r - a[l].l) - (a[r].r - a[r].l));
            upd(1, 1, tmp[0], b[l].l, b[l].r, -1);
            l++;
        }
    }
    write(ans == 2e9 ? -1 : ans);
    return 0;
}
posted @ 2022-12-19 13:48  Chy12321  阅读(32)  评论(0编辑  收藏  举报