Description
在数轴上有 n个闭区间 [l1,r1],[l2,r2],…,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。
对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。
求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。
N<=500000,M<=200000,0≤li≤ri≤10^9
Solution
首先考虑给区间按照长度排序,反正不影响答案是不是(滑稽
那么一段中的首尾决定了这一段的价值,我们只需要每次加入一个新的区间,查询是否有位置被覆盖了m次,每次把最右的区间去掉
要求资瓷动态区间修改、动态查询最值,上线段树即可
一开始没搞-1的情况于是gg了
就酱
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int INF=0x7fffffff;
const int N=2000005;
struct line{int l,r,v;} l[N];
int max[N*4],tag[N*4],b[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void push_down(int now) {
if (!tag[now]) return ;
int tmp=tag[now]; tag[now]=0;
tag[now<<1]+=tmp; max[now<<1]+=tmp;
tag[now<<1|1]+=tmp; max[now<<1|1]+=tmp;
return ;
}
void modify(int now,int tl,int tr,int l,int r,int v) {
if (tl==l&&tr==r) {
max[now]+=v;
tag[now]+=v;
return ;
}
int mid=(tl+tr)>>1;
push_down(now);
if (r<=mid) modify(now<<1,tl,mid,l,r,v);
else if (l>mid) modify(now<<1|1,mid+1,tr,l,r,v);
else {
modify(now<<1,tl,mid,l,mid,v);
modify(now<<1|1,mid+1,tr,mid+1,r,v);
}
max[now]=std:: max(max[now<<1],max[now<<1|1]);
}
int query(int now,int tl,int tr,int l,int r) {
if (tl==l&&tr==r) return max[now];
int mid=(tl+tr)>>1;
push_down(now);
if (r<=mid) return query(now<<1,tl,mid,l,r);
if (l>mid) return query(now<<1|1,mid+1,tr,l,r);
int qx=query(now<<1,tl,mid,l,mid);
int qy=query(now<<1|1,mid+1,tr,mid+1,r);
return std:: max(qx,qy);
}
bool cmp(line a,line b) {
return a.v<b.v;
}
int main(void) {
int n=read(),m=read();
rep(i,1,n) {
int x=read(),y=read();
l[i]=(line) {x,y,y-x};
b[i*2-1]=x; b[i*2]=y;
}
std:: sort(b+1,b+n*2+1);
int size=std:: unique(b+1,b+n*2+1)-b-1;
rep(i,1,n) {
l[i].l=std:: lower_bound(b+1,b+size+1,l[i].l)-b;
l[i].r=std:: lower_bound(b+1,b+size+1,l[i].r)-b;
}
std:: sort(l+1,l+n+1,cmp);
int last=1,ans=INF;
rep(i,1,n) {
modify(1,1,size,l[i].l,l[i].r,1);
while (max[1]>=m) {
ans=std:: min(ans,l[i].v-l[last].v);
modify(1,1,size,l[last].l,l[last].r,-1);
last++;
}
}
if (ans==INF) ans=-1;
printf("%d\n", ans);
return 0;
}