[BZOJ4653][Noi2016]区间 线段树

将所有区间按li-ri排序,那么答案一定是一段连续的区间
有单调性,两个指针扫
一段区间是合法的当且仅当这个区间中存在一个点被超过m个区间覆盖
线段树维护区间最大值,支持区间加法操作即可
notice:l,r达到了1e9,需要离散化

/**************************************************************
    Problem: 4653
    User: di4CoveRy
    Language: C++
    Result: Accepted
    Time:9464 ms
    Memory:67700 kb
****************************************************************/

#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 1000050

#define mid ( (l + r) >> 1 )
#define ls l,mid,t<<1
#define rs mid+1,r,t<<1^1

using namespace std;

struct Monster{ int l,r,w; }Q[N];
bool operator <(Monster p1,Monster p2) { return p1.w < p2.w; }

int tr[4*N],ag[4*N];
int d[2*N],e[2*N],a[2*N];
int ll,rr,v,tp,ans,n,m;
bool cmp(int p1,int p2) { return d[p1] < d[p2]; }
inline void ut(int &x,int y) { x = min(x,y); }

void push_down(int t) {
    ag[t<<1] += ag[t]; ag[t<<1^1] += ag[t];
    tr[t<<1] += ag[t]; tr[t<<1^1] += ag[t];
    ag[t] = 0; return ;
}

void update(int l,int r,int t ){
    if (l > rr || r < ll) return ;
    if (l >= ll && r <= rr) {
        tr[t] += v; ag[t] += v; return;
    }
    push_down(t); update(ls); update(rs);
    tr[t] = max(tr[t<<1],tr[t<<1^1]);
}

int main() {
    scanf("%d%d",&n,&m);
    for (int _=1;_<=n;_++) {
        scanf("%d%d",&Q[_].l,&Q[_].r);
        Q[_].w = Q[_].r - Q[_].l;
        d[2*_-1] = Q[_].l , d[2*_] = Q[_].r;
    }

    //ÀëÉ¢»¯ 
    for (int i=1;i<=2*n;i++) e[i] = i;
    sort(e+1,e+2*n+1,cmp);
    for (int i=1;i<=2*n;i++) 
        a[ e[i] ] = d[ e[i] ] == d[ e[i-1] ] ? a[ e[i-1] ] : a[ e[i-1] ] + 1;
    for (int i=1;i<=n;i++) Q[i].l = a[2*i-1] , Q[i].r = a[2*i];
    tp = a[ e[2*n] ];

    sort(Q+1,Q+n+1);



    int h = 1 , t = 0;
    while (tr[1] < m && t < n) {
        ++t;
        ll = Q[t].l , rr = Q[t].r , v = 1;
        update(1,tp,1);
    }

    ans = 1<<30;
    if (tr[1] >= m) ut(ans, Q[t].w-Q[1].w );
    while (t < n) {
        ll = Q[h].l , rr = Q[h].r , v = -1;
        update(1,tp,1);
        h++;

        while (tr[1] < m && t+1 <= n) {
            t++;
            ll = Q[t].l , rr = Q[t].r , v = 1;
            update(1,tp,1);
        }

        if (tr[1] >= m) ut(ans , Q[t].w-Q[h].w);
    }
    if (ans == (1<<30)) ans = -1;
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值