题目
很显然的想法,区间越长越有利。
我们离散化,按区间长度降序排序。
然后用尺取法,一个个的加入区间头,并且当存在某个位置被大于等于\(M\)个区间覆盖时,删掉区间尾。
我们需要支持区间加和全局最大值,直接线段树维护即可。
代码是很久以前写的了。
#include<bits/stdc++.h>
using namespace std;
namespace IO
{
char ibuf[(1<<21)+1],*iS,*iT;
char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;}
}
using namespace IO;
inline int min(register int a,register int b){return a<b? a:b;}
inline int max(register int a,register int b){return a>b? a:b;}
const int N=500001;
struct node{int l,r,w;}a[N];
inline bool operator<(node a,node b){return a.w<b.w;}
int Hash[N<<1],tag[N<<3],sum[N<<3];
#define lson (p<<1)
#define rson (p<<1|1)
#define mid ((l+r)>>1)
#define same L,R,k
#define left lson,l,mid,same
#define right rson,mid+1,r,same
inline void Pushdown(register int p){if(tag[p])sum[lson]+=tag[p],sum[rson]+=tag[p],tag[lson]+=tag[p],tag[rson]+=tag[p],tag[p]=0;}
inline void Pushup(register int p){sum[p]=max(sum[lson],sum[rson]);}
void Update(int p,int l,int r,int L,int R,int k)
{
if(L>r||l>R) return;
if(L<=l&&r<=R) return (void)(tag[p]+=k,sum[p]+=k);
Pushdown(p),Update(left),Update(right),Pushup(p);
}
int main()
{
register int n=read(),m=read(),num,Min=2147483647,Max=0,head=0,tail=0,ans=2147483647;
for(register int i=1,tot=0;i<=n;++i) Hash[++tot]=a[i].l=read(),Hash[++tot]=a[i].r=read(),a[i].w=a[i].r-a[i].l;
sort(Hash+1,Hash+(n<<1)+1),num=unique(Hash+1,Hash+(n<<1)+1)-(Hash+1),sort(a+1,a+n+1);
for(register int i=1;i<=n;++i) Min=min(Min,a[i].l=lower_bound(Hash+1,Hash+num+1,a[i].l)-Hash),Max=max(Max,a[i].r=lower_bound(Hash+1,Hash+num+1,a[i].r)-Hash);
while(tail<n)
{
while(sum[1]<m&&tail<=n) ++tail,Update(1,Min,Max,a[tail].l,a[tail].r,1);
if(sum[1]<m) break;
while(sum[1]>=m&&tail>=head) ++head,Update(1,Min,Max,a[head].l,a[head].r,-1);
ans=min(ans,a[tail].w-a[head].w);
}
if(ans==2147483647) ans=-1;
return cout<<ans,0;
}