[NOI2016]区间-线段树

一道很巧妙的题。

首先我们需要解决的问题,怎么快速判断选出的m个区间是否存在交。

我们反过来考虑这个问题,

我们每一个选出的区间,就对应的在线段树上区间加1,那么只要存在最大值等于m,就一定有m个区间满足条件了。

那么把区间从小到大排序,一直加到最大值等于m,更新答案,然后删掉最小区间,不停的做下去就好了。

#include <bits/stdc++.h>
#define lson p<<1
#define rson (p<<1)|1
using namespace std;
inline int gi () {
    int x=0, w=0; char ch=0;
    while (! (ch>='0' && ch<='9') ) {
    if (ch=='-') w=1;
    ch=getchar ();
    }
    while (ch>='0' && ch<='9') {
    x= (x<<3) + (x<<1) +  (ch^48);
    ch=getchar ();
    }
    return w?-x:x;
}

const int N=5e5+10;
int n,m,head=1,Ans=0x3f3f3f3f,Num,Ls[N<<1],LS[N<<1],Cnt[N<<3],Tag[N<<3];

struct Sect {
    int l, r, val;
}s[N];
bool Cmp (Sect a, Sect b) {
    return a.val<b.val;
}

void Pushup (int p) {
    Cnt[p]=max (Cnt[lson], Cnt[rson]);
}

void Pushdown (int p) {
    if (!Tag[p]) return;
    Tag[lson]+=Tag[p];
    Tag[rson]+=Tag[p];
    Cnt[lson]+=Tag[p];
    Cnt[rson]+=Tag[p];
    Tag[p]=0;
}

void Modify (int p, int l, int r, int Ml, int Mr, int val) {
    if (l>=Ml && Mr>=r) {
    Cnt[p]+=val;
    Tag[p]+=val;
    return;
    }
    Pushdown (p);
    int Mid= (l+r) >> 1;
    if (Ml<=Mid) Modify (lson, l, Mid, Ml, Mr, val);
    if (Mr>Mid) Modify (rson, Mid+1, r, Ml, Mr, val);
    Pushup (p);
}

int main ()
{
    n=gi (), m=gi ();
    memset (Ls, -1, sizeof (Ls) );
    memset (LS, -1, sizeof (LS) );
    for (int i=1;i<=n;++i) {
    s[i].l=gi (), s[i].r=gi ();
    s[i].val=s[i].r-s[i].l;
    Ls[++Num]=s[i].l, Ls[++Num]=s[i].r;
    }
    sort (Ls+1, Ls+Num+1);
    for (int i=1, j=0;i<=Num;++i) {
    if (Ls[i]!=Ls[i-1]) LS[++j]=Ls[i];
    if (i==Num) {
        Num=j;
        break;
    }
    }
    for (int i=1;i<=n;++i) {
    s[i].l=lower_bound (LS+1, LS+Num+1, s[i].l) -LS;
    s[i].r=lower_bound (LS+1, LS+Num+1, s[i].r) -LS;
    }    
    sort (s+1, s+n+1, Cmp);
    for (int i=1;i<=n;++i) {
    Modify (1, 1, Num, s[i].l, s[i].r, 1);            
    while (Cnt[1]==m) {
        Ans=min (Ans, s[i].val-s[head].val);
        Modify (1, 1, Num, s[head].l, s[head].r, -1);
        head++;
    }
    }
    printf ("%d
", Ans==0x3f3f3f3f?-1:Ans);
    return 0;
}
BY BHLLX
原文地址:https://www.cnblogs.com/Bhllx/p/9930296.html