题意:
分析:
这个题目的限制条件只有两个:
- 选出 (m) 个相交的区间
- 求最大跟最小的差值
我的第一反应是,按处理出每一个线段存在的范围,枚举交点,这样就满足了第一个条件,但是我发现这个第二个条件没法做呀,貌似没有什么数据结构能支持动态查询排名相差为 (m) 的两个数的差值的最小值,所以这个思路可以扔了
我们发现其实限制更大的是第二个条件,所以我们考虑在满足第二个条件的前提下,尽量去满足第一个条件,那么我们按照区间的长度升序排序,双指针扫一遍,每当存在一个点被不小于 (m) 个区间覆盖之后,用双指针的右端点的长度减去左端点的长度,然后左端点++,这样在排序满足第二个条件,然后用一个数据结构维护区间最值满足第一个条件,直接上线段树就好了
代码:
#include<bits/stdc++.h>
#define inl inline
#define reg register
#define mk(x,y) make_pair(x,y)
#define lc rt<<1
#define rc rt<<1|1
#define fir first
#define sec second
using namespace std;
namespace zzc
{
typedef long long ll;
inl ll read()
{
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const ll maxn = 1e6+5;
ll n,m,ans=0x3f3f3f3f3f3f3f3f,cnt;
ll val[maxn<<2],tag[maxn<<2],a[maxn],b[maxn],c[maxn<<1];
pair<ll,pair<ll,ll> > p[maxn];
inl void pushup(ll rt)
{
val[rt]=max(val[lc],val[rc]);
}
inl void pushdown(ll rt)
{
if(tag[rt])
{
val[lc]+=tag[rt];tag[lc]+=tag[rt];
val[rc]+=tag[rt];tag[rc]+=tag[rt];
tag[rt]=0;
}
}
void modify(ll rt,ll l,ll r,ll ql,ll qr,ll k)
{
if(ql<=l&&r<=qr)
{
val[rt]+=k;
tag[rt]+=k;
return ;
}
ll mid=(l+r)>>1;
pushdown(rt);
if(ql<=mid) modify(lc,l,mid,ql,qr,k);
if(qr>mid) modify(rc,mid+1,r,ql,qr,k);
pushup(rt);
}
void work()
{
n=read();m=read();
for(reg ll i=1;i<=n;i++)
{
a[i]=read();c[++cnt]=a[i];
b[i]=read();c[++cnt]=b[i];
}
sort(c+1,c+cnt+1);
cnt=unique(c+1,c+cnt+1)-c-1;
for(reg ll i=1;i<=n;i++)
{
ll len=b[i]-a[i]+1;
b[i]=lower_bound(c+1,c+cnt+1,b[i])-c;
a[i]=lower_bound(c+1,c+cnt+1,a[i])-c;
p[i]=mk(len,mk(a[i],b[i]));
}
sort(p+1,p+n+1);
for(reg ll i=1,j=1;i<=n;i++)
{
modify(1,1,cnt,p[i].sec.fir,p[i].sec.sec,1);
while(val[1]>=m)
{
ans=min(ans,p[i].fir-p[j].fir);
modify(1,1,cnt,p[j].sec.fir,p[j].sec.sec,-1);
j++;
}
}
if(ans==0x3f3f3f3f3f3f3f3f) puts("-1");
else printf("%lld
",ans);
}
}
int main()
{
zzc::work();
return 0;
}