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
双指针扫一下即可,难得的noi水题
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define M 1000010 6 #define int long long 7 #define ls node<<1 8 #define rs node<<1|1 9 using namespace std; 10 int read() 11 { 12 char ch=getchar();int x=0; 13 while(ch>'9'||ch<'0') ch=getchar(); 14 while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); 15 return x; 16 } 17 18 int l,r,n,m,tmp,ans=1e18; 19 int b[M<<2],cnt[M<<2],tag[M<<2]; 20 struct point{int l,r;}a[M]; 21 bool cmp(point a1,point a2) {return a1.r-a1.l<a2.r-a2.l;} 22 23 void getans(int l,int r) 24 { 25 ans=min(ans,b[a[r].r]-b[a[r].l]+b[a[l].l]-b[a[l].r]); 26 } 27 28 int get(int x) 29 { 30 int l=1,r=tmp; 31 while(l<=r) 32 { 33 int mid=(l+r)/2; 34 if(b[mid]==x) return mid; 35 if(b[mid]<x) l=mid+1; 36 else r=mid-1; 37 } 38 } 39 40 void push(int node) 41 { 42 if(tag[node]!=0) 43 { 44 tag[ls]+=tag[node]; 45 tag[rs]+=tag[node]; 46 cnt[ls]+=tag[node]; 47 cnt[rs]+=tag[node]; 48 tag[node]=0; 49 } 50 } 51 52 void change(int node,int l,int r,int l1,int r1,int v) 53 { 54 if(l1<=l&&r1>=r) 55 { 56 cnt[node]+=v; 57 tag[node]+=v; 58 return; 59 } 60 if(l1>r||r1<l) return; 61 int mid=(l+r)/2; push(node); 62 change(ls,l,mid,l1,r1,v); 63 change(rs,mid+1,r,l1,r1,v); 64 cnt[node]=max(cnt[ls],cnt[rs]); 65 } 66 67 main() 68 { 69 n=read(); m=read(); 70 for(int i=1;i<=n;i++) 71 { 72 a[i].l=read(),a[i].r=read(); 73 b[++tmp]=a[i].l,b[++tmp]=a[i].r; 74 } 75 sort(a+1,a+1+n,cmp); 76 sort(b+1,b+1+tmp); 77 tmp=unique(b+1,b+1+tmp)-b-1; 78 for(int i=1;i<=n;i++) 79 { 80 a[i].l=get(a[i].l); 81 a[i].r=get(a[i].r); 82 } 83 while(1) 84 { 85 while(cnt[1]>=m) 86 { 87 getans(l,r); 88 change(1,1,tmp,a[l].l,a[l].r,-1); 89 l++; 90 } 91 if(r==n) break; 92 r++; 93 change(1,1,tmp,a[r].l,a[r].r,1); 94 } 95 if(ans==1e18) puts("-1"); 96 else printf("%lld",ans); 97 return 0; 98 }