[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 }