bzoj4653 [Noi2016]区间(线段树)

按区间长度从小到大排序,枚举最小的区间长度,去覆盖线段,直到存在一个点被覆盖了>=m次,此时的区间长度就是最大的,更新答案。然后删掉目前最小值,继续尝试。复杂度 O(nlogn)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 500010
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,m,aa[N<<1],tot=0,ans=inf;
struct node{
    int cov,mx;
}tr[N<<3];
struct Lines{
    int x,y,len;
    friend bool operator<(Lines a,Lines b){return a.len<b.len;}
}a[N];
inline void pushup(int p){
    tr[p].mx=max(tr[p<<1].mx,tr[p<<1|1].mx);
}
inline void docov(int p,int val){
    tr[p].cov+=val;tr[p].mx+=val;
}
inline void pushdown(int p){
    if(!tr[p].cov) return;docov(p<<1,tr[p].cov);docov(p<<1|1,tr[p].cov);tr[p].cov=0;
}
inline void cover(int p,int l,int r,int x,int y,int val){
    if(x<=l&&r<=y){docov(p,val);return;}
    int mid=l+r>>1;pushdown(p);
    if(x<=mid) cover(p<<1,l,mid,x,y,val);
    if(y>mid) cover(p<<1|1,mid+1,r,x,y,val);pushup(p);
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();m=read();
    for(int i=1;i<=n;++i) a[i].x=aa[++tot]=read(),a[i].y=aa[++tot]=read(),a[i].len=a[i].y-a[i].x;
    sort(aa+1,aa+tot+1);tot=unique(aa+1,aa+tot+1)-aa-1;
    for(int i=1;i<=n;++i){
        a[i].x=lower_bound(aa+1,aa+tot+1,a[i].x)-aa;
        a[i].y=lower_bound(aa+1,aa+tot+1,a[i].y)-aa;
    }sort(a+1,a+n+1);int now=1;
    for(int i=1;i<=n;++i){
        while(tr[1].mx<m&&now<=n) cover(1,1,tot,a[now].x,a[now].y,1),++now;
        if(tr[1].mx<m) break;ans=min(ans,a[now-1].len-a[i].len);
        cover(1,1,tot,a[i].x,a[i].y,-1);
    }if(ans==inf) puts("-1");
    else printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值