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
3 5
1 2
3 4
2 2
1 5
1 4
Sample Output
2
【解题方法】
容易想到先按照区间的长度来排序之后,明显有单调性,要统计直接用双指针移动维护答案就好了。用线段树维护一下出现次数。
【AC 代码】
//
//Created by just_sort 2016/8/19
//All Rights Reserved
//
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1000010;
const int inf = 0x3fffffff;
struct query{
int l,r,len;
bool operator<(const query &rhs) const{
return len<rhs.len;
}
}q[maxn*2];
struct node{
int l,r;
int maxx,lazy;
}Tree[maxn*4];
vector<int>xs;
void pushup(int rt)
{
Tree[rt].maxx=max(Tree[rt*2].maxx,Tree[rt*2+1].maxx);
}
void pushdown(int rt)
{
if(Tree[rt].lazy){
Tree[rt*2].lazy+=Tree[rt].lazy;
Tree[rt*2+1].lazy+=Tree[rt].lazy;
Tree[rt*2].maxx+=Tree[rt].lazy;
Tree[rt*2+1].maxx+=Tree[rt].lazy;
Tree[rt].lazy=0;
}
}
void Build(int l,int r,int rt)
{
Tree[rt].l=l,Tree[rt].r=r;
Tree[rt].lazy=0,Tree[rt].maxx=0;
if(l==r) return ;
int mid=(l+r)/2;
Build(l,mid,rt*2);
Build(mid+1,r,rt*2+1);
}
void update(int L,int R,int v,int rt)
{
if(L==Tree[rt].l&&Tree[rt].r==R){
Tree[rt].lazy+=v;
Tree[rt].maxx+=v;
return ;
}
pushdown(rt);
int mid=(Tree[rt].l+Tree[rt].r)/2;
if(R<=mid) update(L,R,v,rt*2);
else if(L>mid) update(L,R,v,rt*2+1);
else{
update(L,mid,v,rt*2);
update(mid+1,R,v,rt*2+1);
}
pushup(rt);
}
int main()
{
xs.clear();
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].len=q[i].r-q[i].l;
xs.push_back(q[i].l);
xs.push_back(q[i].r);
}
sort(xs.begin(),xs.end());
xs.resize(unique(xs.begin(),xs.end())-xs.begin());
int key=xs.size();
for(int i=1; i<=n; i++){
q[i].l=lower_bound(xs.begin(),xs.end(),q[i].l)-xs.begin()+1;
q[i].r=lower_bound(xs.begin(),xs.end(),q[i].r)-xs.begin()+1;
}
sort(q+1,q+n+1);
//cout<<key<<endl;
Build(1,key,1);
//two pointers
int ans=inf,i,j=0;
for(i=1; i<=n; i++){
while(j<n&&Tree[1].maxx<m) j++,update(q[j].l,q[j].r,1,1);
if(Tree[1].maxx>=m) ans = min(ans,q[j].len-q[i].len);
else break;
update(q[i].l,q[i].r,-1,1);
}
if(ans==inf) ans=-1;
printf("%d\n",ans);
return 0;
}