bzoj4653 [Noi2016]区间

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4653

【题解】

首先把区间按长度从小到大排好序。

那么取一些区间,花费为长度最大-长度最小,相当于把这个长度区间里面的区间都取了。

求是不是有一个位置被覆盖超过了m次。

那么这个用two-pointer和线段树就能实现啦!

# include <vector>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, m;
struct intervals {
    int l, r;
    intervals() {}
    intervals(int l, int r) : l(l), r(r) {}
    friend bool operator < (intervals a, intervals b) {
        return a.r-a.l < b.r-b.l;
    }
}p[M], a[M];

vector<int> ps;

namespace SGT {
    const int M = 4e6 + 10;
    int w[M], lazy[M];
    # define ls (x<<1)
    # define rs (x<<1|1)
    inline void down(int x) {
        if(!x) return ;
        if(!lazy[x]) return ;
        w[ls] += lazy[x], lazy[ls] += lazy[x];
        w[rs] += lazy[x], lazy[rs] += lazy[x];
        lazy[x] = 0;
    }
    inline void change(int x, int l, int r, int L, int R, int d) {
        if(L <= l && r <= R) {
            w[x] += d;
            lazy[x] += d;
            return ;
        }
        down(x);
        int mid = l+r>>1;
        if(L <= mid) change(ls, l, mid, L, R, d);
        if(R > mid) change(rs, mid+1, r, L, R, d);
        w[x] = max(w[ls], w[rs]);
    }
    inline int get() {
        return w[1];
    }
}

int main() {
    cin >> n >> m;
    for (int i=1; i<=n; ++i) scanf("%d%d", &p[i].l, &p[i].r);
    sort(p+1, p+n+1);
    for (int i=1; i<=n; ++i) ps.push_back(p[i].l), ps.push_back(p[i].r);
    sort(ps.begin(), ps.end());
    ps.erase(unique(ps.begin(), ps.end()), ps.end());
    for (int i=1; i<=n; ++i) {
        a[i].l = lower_bound(ps.begin(), ps.end(), p[i].l) - ps.begin() + 1;
        a[i].r = lower_bound(ps.begin(), ps.end(), p[i].r) - ps.begin() + 1;
    }
    int mx = ps.size(), ans = 1e9;
    for (int l=1, r=0; l<=n; ++l) {
        if(SGT::get() != m) {
            while(r<n) {
                ++r;
                SGT::change(1, 1, mx, a[r].l, a[r].r, 1);
                if(SGT::get() == m) break;
            }
        }
        if(SGT::get() != m) break;
        ans = min(ans, p[r].r - p[r].l - p[l].r + p[l].l);
        SGT::change(1, 1, mx, a[l].l, a[l].r, -1);
    }
    if(ans == 1e9) cout << -1;
    else cout << ans;
    return 0;
}
View Code

 

posted @ 2017-05-29 14:09  Galaxies  阅读(182)  评论(0编辑  收藏  举报