洛谷P1712[NOI2016]区间

线段树+尺取法。
我们先离散化一次,然后按照区间长度排序,每次一位一位往后移。
至于如何判断覆盖了多少个点,我们用一个线段树维护即可。

My Code:

#include <bits/stdc++.h>
#define il inline
#define temp template<class T>
#define lson(o) (o << 1)
#define rson(o) (o << 1 | 1)
const int INF = 0x3f3f3f3f;
const int MAXN = 5e5 + 10;
using namespace std;
temp il void rd(T& res) {
    res = 0;char c;bool sign = 0;
    for(c = getchar();!isdigit(c);c = getchar()) sign |= c == '-';
    for(;isdigit(c);c = getchar()) res = (res << 1) + (res << 3) + (c ^ 48);
    (sign) && (res = -res);
    return;
}
temp il T _min(T x,T y) {
    return x < y ? x : y;
}
temp il T _max(T x,T y) {
    return x > y ? x : y;
}
int l[MAXN << 1],r[MAXN << 1];
int n,m,i,j,k,cnt,tot,Max;
struct Node {
    int len,id;
}a[MAXN << 2];
struct LSH {
    int x,id;
}b[MAXN << 2];
int tr[MAXN << 3],tag[MAXN << 3];
il bool cmpN(Node a,Node b) {
    return a.len < b.len;
}
il bool cmpL(LSH a,LSH b) {
    return a.x < b.x;
}
il void pushup(int o) {
    tr[o] = _max(tr[lson(o)],tr[rson(o)]);
    return;
}
il void init(int o,int l,int r,int val) {
    tr[o] += val;
    tag[o] += val;
    return;
}
il void pushdown(int o,int l,int r) {
    if(tag[o]) {
        int mid = l + r >> 1;
        init(lson(o),l,mid,tag[o]);
        init(rson(o),mid + 1,r,tag[o]);
        tag[o] = 0;
    }
    return;
}
void modify(int ml,int mr,int l,int r,int o,int val) {       
    if(l > mr || r < ml) return;
    if(ml <= l && r <= mr) {
        tr[o] += val;
        tag[o] += val;
        return;
    }
    pushdown(o,l,r);
    int mid = l + r >> 1;
    if(ml <= mid) modify(ml,mr,l,mid,lson(o),val);
    if(mid < mr)  modify(ml,mr,mid + 1,r,rson(o),val);
    pushup(o);
    return;
}
int main() {
    rd(n);rd(m);
    for(int i = 1,rl,rr;i <= n;i++) {
        rd(rl);rd(rr);
        a[i].len = rr - rl;a[i].id = i;
        b[++cnt].x = rl;b[cnt].id = i;
        b[++cnt].x = rr;b[cnt].id = i;
    }
    sort(b + 1,b + cnt + 1,cmpL);b[0].x = -1;
    for(int i = 1;i <= cnt;i++) {
        if(b[i].x != b[i - 1].x) tot++;
        if(!l[b[i].id]) l[b[i].id] = tot;   
        else r[b[i].id] = tot; 
    }
    Max = tot;int sl = 0,sr = 0,ans = INF;
    sort(a + 1,a + n + 1,cmpN);
    while(1) {
        while(tr[1] < m && sr <= n) {    
            sr++;
            int x = l[a[sr].id],y = r[a[sr].id];
            modify(x,y,1,Max,1,1);
        }
        if(tr[1] < m) break;
        while(tr[1] >= m && sl <= n) {
            sl++;int x = l[a[sl].id],y = r[a[sl].id];
            modify(x,y,1,Max,1,-1);
        }
        ans = _min(ans,a[sr].len - a[sl].len);
    }
    ans != INF ? printf("%d\n",ans) : puts("-1");
    return 0;
} 

猜你喜欢

转载自www.cnblogs.com/Sai0511/p/10362905.html