考虑对区间长度排序,然后尺取做,显然当左端点右移时,要满足答案,右端点不可能左移。所以尺取是可行的,接下来是怎么统计一个点出现的次数,显然就是区间修改,单点查询。这不线段树裸题嘛,没了。
code
// Problem: P1712 [NOI2016] 区间
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1712
// Memory Limit: 250 MB
// Time Limit: 1000 ms
// Date: 2021-07-14 18:39:44
// --------by Herio--------
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=5e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0)
void Print(int *a,int n){
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\n",a[n]);
}
int n,m;
#define lx x<<1
#define rx x<<1|1
struct node{
int l,r,mx,lz;
}a[N<<3];
void re(int x){
a[x].mx=max(a[lx].mx,a[rx].mx);
}
void bud(int x,int l,int r){
a[x].l=l,a[x].r=r,a[x].mx=0;
if(l==r) return;
int m=l+r>>1;
bud(lx,l,m),bud(rx,m+1,r);
}
void pushdown(int x){
if(a[x].lz){
a[lx].mx+=a[x].lz,a[rx].mx+=a[x].lz;
a[lx].lz+=a[x].lz,a[rx].lz+=a[x].lz;
a[x].lz=0;
}
}
void upd(int x,int l,int r,int v){
if(a[x].l>=l&&a[x].r<=r){
a[x].mx+=v;
a[x].lz+=v;return;
}
pushdown(x);
int m=a[x].l+a[x].r>>1;
if(l<=m) upd(lx,l,r,v);
if(r>m) upd(rx,l,r,v);
re(x);
}
struct interval{
int x,y,c;
}b[N];
int c[N<<1],cnt;
bool cmp(interval &a,interval &b){
return a.c<b.c;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d%d",&b[i].x,&b[i].y),c[++cnt]=b[i].x;
c[++cnt]=b[i].y;
b[i].c=b[i].y-b[i].x;
}
sort(c+1,c+cnt+1);
cnt=unique(c+1,c+cnt+1)-c-1;
for(int i=1;i<=n;i++){
b[i].x=lower_bound(c+1,c+cnt+1,b[i].x)-c;
b[i].y=lower_bound(c+1,c+cnt+1,b[i].y)-c;
}
bud(1,1,cnt);
int ans=inf;
int p=1;
sort(b+1,b+n+1,cmp);
for(int i=1;i<=n;i++){
upd(1,b[i].x,b[i].y,1);
while(a[1].mx==m){
upd(1,b[p].x,b[p].y,-1);
ans=min(ans,b[i].c-b[p++].c);
}
}
ans=ans==inf?-1:ans;
printf("%d\n",ans);
return 0;
}