Description
在数轴上有 n个闭区间 [l1,r1],[l2,r2],…,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。
对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。
求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。
Input
第一行包含两个正整数 n,m用空格隔开,意义如上文所述。保证 1≤m≤n
接下来 n行,每行表示一个区间,包含用空格隔开的两个整数 li 和 ri 为该区间的左右端点。
N<=500000,M<=200000,0≤li≤ri≤10^9
Output
只有一行,包含一个正整数,即最小花费。
Sample Input
6 3
3 5
1 2
3 4
2 2
1 5
1 4
Sample Output
2
题解
首先我们将所有区间按照长度排序,然后我们依次扫描每个区间,用线段树找到它第一次有点覆盖次数超过k的另一个区间,更新一下答案,因为左端点递增时右端点也一定递增,所以维护两个指针扫一下即可。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<string>
#include<algorithm>
#include<ctime>
#include<cmath>
using namespace std;
struct xianduan
{
int l,r,maxx,lazy;
void add(int val)
{
maxx+=val;
lazy+=val;
}
}a[5000000];
void make_tree(int o,int l,int r)
{
a[o].l=l;
a[o].r=r;
a[o].maxx=0;
a[o].lazy=0;
if(l==r) return;
int mid=l+r>>1;
make_tree(2*o,l,mid);
make_tree(2*o+1,mid+1,r);
}
void push_down(int o)
{
if(a[o].l==a[o].r) return;
if(!a[o].lazy) return;
a[2*o].add(a[o].lazy);
a[2*o+1].add(a[o].lazy);
a[o].lazy=0;
}
void change(int o,int l,int r,int d)
{
if(a[o].r<l || a[o].l>r) return;
push_down(o);
if(a[o].l>=l && a[o].r<=r)
{
a[o].add(d);
return;
}
change(2*o,l,r,d);
change(2*o+1,l,r,d);
a[o].maxx=max(a[2*o].maxx,a[2*o+1].maxx);
}
struct interval
{
int l,r,val;
bool operator < (interval b) const
{
return val<b.val;
}
}q[600000];
int dd[1100000];
int top=0;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d%d",&q[i].l,&q[i].r),q[i].val=q[i].r-q[i].l+1,dd[++top]=q[i].l,dd[++top]=q[i].r;
sort(dd+1,dd+1+top);
top=unique(dd+1,dd+1+top)-dd-1;
for(int i=1;i<=n;i++) q[i].l=lower_bound(dd+1,dd+1+top,q[i].l)-dd,q[i].r=lower_bound(dd+1,dd+1+top,q[i].r)-dd;
sort(q+1,q+1+n);
int r=1;
int ans=2147483647;
make_tree(1,1,top);
for(int i=1;i<=n;i++)
{
while(a[1].maxx<m && r<=n)
{
change(1,q[r].l,q[r].r,1);
r++;
}
if(a[1].maxx<m) break;
ans=min(ans,q[r-1].val-q[i].val);
change(1,q[i].l,q[i].r,-1);
}
if(ans==2147483647) cout<<-1;
else cout<<ans<<endl;
return 0;
}