LOJ P2086 BZOJ P4653「NOI2016」区间 【线段树】【离散化】

比较水。

按照坐标作为叶子结点建立线段树,维护该点被选择的区间覆盖了的次数。

将每个区间按照长度排序,在合法条件下每次试探来更新答案。

坐标太大,所以将坐标离散化。

#include <bits/stdc++.h>
#define LL long long
#define For(I,X,Y) for(LL I=(X);I<=(Y);I++)
#define Fora(I,X,Y) for(LL I=(X);I<(Y);I++)
#define ForDown(I,X,Y) for(LL I=(X);I>=(Y);I--)
using namespace std;
 
inline LL Read(){
    LL X=0;char CH=getchar();bool F=0;
    while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
    while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
    return F?-X:X;
}
 
inline void Write(LL X){
    if(X<0)X=-X,putchar('-');
    if(X>9)Write(X/10);putchar(X%10+48);
}
 
const LL Inf=1e18;
const LL Max=5e5+5;
LL N,M,Tot,Ans=Inf,Tmp[Max<<1];
 
#define LSon (P<<1)
#define RSon (P<<1|1)
 
struct Segment_Tree{
    LL X,Y,Mx,Lazy;
}Tree[Max<<3];
 
struct Node{
    LL L,R,Len;
}Sec[Max];
 
bool Cmp(Node P,Node Q){
    return P.Len<Q.Len;
}
 
void PushUp(LL P){
    Tree[P].Mx=max(Tree[LSon].Mx,Tree[RSon].Mx);
}
 
void PushDown(LL P){
    Tree[LSon].Lazy+=Tree[P].Lazy;
    Tree[LSon].Mx+=Tree[P].Lazy;
    Tree[RSon].Lazy+=Tree[P].Lazy;
    Tree[RSon].Mx+=Tree[P].Lazy;Tree[P].Lazy=0;
}
 
void MakeTree(LL P,LL X,LL Y){
    Tree[P].X=X,Tree[P].Y=Y;
    if(X<Y) {
        MakeTree(LSon,X,X+Y>>1);
        MakeTree(RSon,(X+Y>>1)+1,Y);
    } 
}
 
void Update(LL P,LL X,LL Y,LL Z){
    if(Tree[P].Y<X||Y<Tree[P].X) return;
     
    if(X<=Tree[P].X&&Tree[P].Y<=Y) {
        Tree[P].Mx+=Z;Tree[P].Lazy+=Z;return;
    }
     
    if(Tree[P].Lazy!=0) PushDown(P);
     
    Update(LSon,X,Y,Z);Update(RSon,X,Y,Z);PushUp(P);
}
 
int main(){
    N=Read(),M=Read();
     
     
    For(I,1,N) {
        Sec[I].L=Read();
        Sec[I].R=Read();
        Sec[I].Len=Sec[I].R-Sec[I].L;
        Tmp[++Tot]=Sec[I].L,Tmp[++Tot]=Sec[I].R;
    }
     
    sort(Tmp+1,Tmp+1+Tot);Tot=unique(Tmp+1,Tmp+1+Tot)-Tmp-1;
     
    sort(Sec+1,Sec+1+N,Cmp);
    For(I,1,N) Sec[I].L=lower_bound(Tmp+1,Tmp+1+Tot,Sec[I].L)-Tmp,Sec[I].R=lower_bound(Tmp+1,Tmp+1+Tot,Sec[I].R)-Tmp;
     
    MakeTree(1,1,Tot);
     
    LL Left=0,Right=0;
 
    while(true) {
        while(Tree[1].Mx<M&&Right<N) Right++,Update(1,Sec[Right].L,Sec[Right].R,1);
         
        if(Tree[1].Mx<M) break;
         
        while(Tree[1].Mx>=M&&Left<N) Left++,Update(1,Sec[Left].L,Sec[Left].R,-1);
         
        Ans=min(Ans,Sec[Right].Len-Sec[Left].Len);
    }
     
    if(Ans==Inf) Write(-1);
    else Write(Ans);
     
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值