题目描述
在数轴上有 NN 个闭区间 [l_1,r_1],[l_2,r_2],...,[l_n,r_n][l1,r1],[l2,r2],...,[ln,rn] 。现在要从中选出 MM 个区间,使得这 MM 个区间共同包含至少一个位置。换句话说,就是使得存在一个 xx ,使得对于每一个被选中的区间 [l_i,r_i][li,ri] ,都有 l_i≤x≤r_ili≤x≤ri 。
对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [l_i,r_i][li,ri] 的长度定义为 r_i-l_iri−li ,即等于它的右端点的值减去左端点的值。
求所有合法方案中最小的花费。如果不存在合法的方案,输出 -1−1 。
输入输出格式
输入格式:
第一行包含两个正整数 N,MN,M 用空格隔开,意义如上文所述。保证 1≤M≤N1≤M≤N
接下来 NN 行,每行表示一个区间,包含用空格隔开的两个整数 l_ili 和 r_iri 为该区间的左右端点。
N<=500000,M<=200000,0≤li≤ri≤10^9N<=500000,M<=200000,0≤li≤ri≤109
输出格式:
只有一行,包含一个正整数,即最小花费。
输入输出样例
说明
Solution:
今天PKU学长HRZ讲课,说到了本题,然后思路比较巧妙。
方法就是对区间离散后,按原长度从小到大排序,然后用一个队列维护两个指针$l,r$,$O(n)$的去加入区间$s[l,r]+=1$,用线段树维护区间最大值,若区间最大值$\geq m$则从前往后把加入的区间删除,直到区间最大值刚好$< m$,那么用$l-1$所保存的长度和当前加入的区间长度差去更新答案,然后就没了。
代码:
1 #include<bits/stdc++.h> 2 #define il inline 3 #define ll long long 4 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) 5 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--) 6 #define lson l,m,rt<<1 7 #define rson m+1,r,rt<<1|1 8 using namespace std; 9 const int N=800005; 10 int n,m,maxn[N<<3],add[N<<3],ans=0x7fffffff; 11 int l=1,r; 12 int *lst[N<<1],cnt,tot; 13 struct node{ 14 int l,r,len; 15 bool operator<(const node &a)const{return len<a.len;} 16 }a[N],Q[N]; 17 18 il bool cmp(const int *a,const int *b) {return *a<*b;} 19 20 il int gi(){ 21 int a=0;char x=getchar();bool f=0; 22 while((x<'0'||x>'9')&&x!='-')x=getchar(); 23 if(x=='-')x=getchar(),f=1; 24 while(x>='0'&&x<='9')a=(a<<1)+(a<<3)+x-48,x=getchar(); 25 return f?-a:a; 26 } 27 28 il void pushup(int rt){maxn[rt]=max(maxn[rt<<1],maxn[rt<<1|1]);} 29 30 il void pushdown(int rt,int len){ 31 if(add[rt]){ 32 add[rt<<1]+=add[rt], 33 add[rt<<1|1]+=add[rt]; 34 maxn[rt<<1]+=add[rt], 35 maxn[rt<<1|1]+=add[rt]; 36 add[rt]=0; 37 } 38 } 39 40 il void update(int L,int R,int k,int l,int r,int rt){ 41 pushdown(rt,r-l+1); 42 if(L<=l&&R>=r){maxn[rt]+=k;add[rt]=k;return;} 43 int m=l+r>>1; 44 if(L<=m) update(L,R,k,lson); 45 if(R>m) update(L,R,k,rson); 46 pushup(rt); 47 } 48 49 int main(){ 50 n=gi(),m=gi(); 51 For(i,1,n) a[i].l=gi(),a[i].r=gi(),a[i].len=a[i].r-a[i].l,lst[++cnt]=&a[i].l,lst[++cnt]=&a[i].r; 52 sort(lst+1,lst+cnt+1,cmp); 53 int k=-1; 54 For(i,1,cnt) { 55 if(*lst[i]!=k) k=*lst[i],*lst[i]=++tot; 56 else *lst[i]=tot; 57 } 58 sort(a+1,a+n+1); 59 For(i,1,n) { 60 Q[++r].l=a[i].l,Q[r].r=a[i].r,Q[r].len=a[i].len; 61 update(a[i].l,a[i].r,1,1,tot,1); 62 if(maxn[1]>=m){ 63 while(l<=r&&maxn[1]>=m){ 64 update(Q[l].l,Q[l].r,-1,1,tot,1); 65 l++; 66 } 67 if(maxn[1]<m) ans=min(a[i].len-Q[l-1].len,ans); 68 } 69 } 70 cout<<(ans==0x7fffffff?-1:ans); 71 return 0; 72 }