[NOI2014]区间

background

      一开始的时候一脸懵逼,然后旁边syk神仙说了一句"按长度排序",突然恍然大悟 

题意

solution

    离散化+按长度排序

      然后two points 扫一遍,右端点每右移一位,就把该点对应的区间+1,左端点每右移一位,就把该点对应的区间-1,如果总区间的最大值 >=m则可行

code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 3000000
#define ls (x<<1)
#define rs (x<<1|1)
#define mid ((l+r)>>1)
using namespace std;
const int inf=2100000000;
int res[N<<3],lazy[N<<3];
int L[N],R[N],id[N],plk[N];
int n,m,tot=0;
void update(int x){res[x]=max(res[ls],res[rs]);}
void push_down(int x){
    if(lazy[x])lazy[ls]+=lazy[x],lazy[rs]+=lazy[x],res[ls]+=lazy[x],res[rs]+=lazy[x],lazy[x]=0;
}
void modify(int x,int l,int r,int nl,int nr,int k){
    push_down(x);
    if(nl<=l&&r<=nr){lazy[x]+=k;res[x]+=k;return;}
    if(mid>=nl)modify(ls,l,mid,nl,nr,k);
    if(mid<nr)modify(rs,mid+1,r,nl,nr,k);
    update(x);
}
bool cmp(int a,int b){return (R[a]-L[a])>(R[b]-L[b]);}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){scanf("%d%d",L+i,R+i);plk[++tot]=L[i],plk[++tot]=R[i];}
for(int i=1;i<=n;i++)id[i]=i;
sort(id+1,id+n+1,cmp);
sort(plk+1,plk+tot+1);tot=unique(plk+1,plk+tot+1)-plk-1;
for(int i=1;i<=n;i++)L[i]=lower_bound(plk+1,plk+tot+1,L[i])-plk,R[i]=lower_bound(plk+1,plk+tot+1,R[i])-plk;//离散化
int pos1,pos2=0,ans=inf;
for(pos1=1;pos1<=n;pos1++){
    while(res[1]<m&&pos2<n){pos2++;modify(1,1,tot,L[id[pos2]],R[id[pos2]],1);}if(res[1]<m)break;
    ans=min(ans,(plk[R[id[pos1]]]-plk[L[id[pos1]]])-(plk[R[id[pos2]]]-plk[L[id[pos2]]]));
    modify(1,1,tot,L[id[pos1]],R[id[pos1]],-1);
}//two points
printf("%d\n",(ans==inf)?-1:ans);//压行压行awa 
}

 

posted @ 2019-09-29 10:44  stepsys  阅读(...)  评论(...编辑  收藏