题意
在数轴上有 n个闭区间 [l1,r1],[l2,r2],…,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。
对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。
求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。
解析
我们用一棵线段树来保存点的覆盖情况,可以用最大值找出被覆盖的点,然后采用类似于尺取法的思想,从前往后扫,每次满足是判断,取最小值。(因为区间本身的值是不计入贡献的,只要计算差值)。注意数字要先离散化。
#include <cstdio>
#include <algorithm>
#define Rep( i , _begin , _end ) for(int i=(_begin);i<=(_end);i++)
#define For( i , _begin , _end ) for(int i=(_begin);i!=(_end);i++)
#define Lop( i , _begin , _end ) for(int i=(_begin);i>=(_end);i--)
#define Dnt( i , _begin , _end ) for(int i=(_begin);i!=(_end);i--)
using std :: max;
using std :: min;
using std :: sort;
using std :: unique;
using std :: lower_bound;
const int maxx = 1000000 + 25;
const int Inf = (unsigned)(-1) >> 1;
int n,m,x,y,z,ans = Inf,cnt,L,R,j;
int T[maxx<<2],Add[maxx<<2];
int num[maxx<<1],val[maxx];
namespace Segment_Tree{
void pushdown(int i,int l,int r){
int mid = (l+r) >> 1;
T[i<<1] += Add[i];T[i<<1|1] += Add[i];
Add[i<<1] += Add[i];Add[i<<1|1] += Add[i];Add[i] = 0;
}
void modify(int i,int x,int y,int l,int r,int k){
if(x <= l && r <= y) {T[i] += k;Add[i] += k;return;}
int mid = (l+r) >> 1;if(Add[i]) pushdown(i,l,r);
if(x <= mid) modify(i<<1,x,y,l,mid,k);
if(y > mid) modify(i<<1|1,x,y,mid+1,r,k);
T[i] = max(T[i<<1] , T[i<<1|1]);
}
int Query(int i,int x,int y,int l,int r){
if(x <= l && r <= y) return T[i];int ans = -Inf;
int mid = (l+r) >> 1;if(Add[i]) pushdown(i,l,r);
if(x <= mid) ans = max(ans,Query(i<<1,x,y,l,mid));
if(y > mid) ans = max(ans,Query(i<<1|1,x,y,mid+1,r));
return ans;
}
}
using namespace Segment_Tree;
struct Edges{
int l;
int r;
int v;
}E[maxx<<1];
bool cmp(Edges a,Edges b){
return a.v < b.v;
}
int main(){
scanf("%d%d",&n,&m);
Rep( i , 1 , n ){
scanf("%d%d",&x,&y);
E[i].l = x;E[i].r = y;E[i].v = y-x;
num[++cnt] = x;num[++cnt] = y;
}
sort(E+1,E+n+1,cmp);
sort(num+1,num+cnt+1);
int tot = unique(num+1,num+cnt+1) - num - 1;
Rep( i , 1 , n ){
while (T[1] < m){
if (j == n) break; j++;
int ln = lower_bound(num+1,num+tot+1,E[j].l) - num;
int rn = lower_bound(num+1,num+tot+1,E[j].r) - num;
modify(1,ln,rn,1,tot,1);
}
if(T[1] == m) ans = min(ans,E[j].v-E[i].v);
int ln = lower_bound(num+1,num+tot+1,E[i].l) - num;
int rn = lower_bound(num+1,num+tot+1,E[i].r) - num;
modify(1,ln,rn,1,tot,-1);
}
printf("%d\n",ans == Inf? -1 : ans);
return 0;
}