[BZOJ5102]Prawnicy
Description
定义一个区间(l,r)的长度为r-l,空区间的长度为0。
给定数轴上n个区间,请选择其中恰好k个区间,使得交集的长度最大。
Input
第一行包含两个正整数n,k(1<=k<=n<=1000000),表示区间的数量。
接下来n行,每行两个正整数l,r(1<=l<r<=10^9),依次表示每个区间。
Output
第一行输出一个整数,即最大长度。
第二行输出k个正整数,依次表示选择的是输入文件中的第几个区间。
若有多组最优解,输出任意一组。
Sample Input
6 3
3 8
4 12
2 6
1 10
5 9
11 12
3 8
4 12
2 6
1 10
5 9
11 12
Sample Output
4
1 2 4
1 2 4
HINT
Source
做这道题的时候状态还不错,很快就想出来了
其实也是一个比较套路的贪心,假如我们把所有的$L$从小到大排序,那么限制区间大小的就是最大的$L$
这时我们把最大的$L$和最小的$R$计算一下答案,最小值可以用堆来维护
如果当前堆中元素的个数超过$k$,我们就选择$R$最小的弹出
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<algorithm> 5 #define M 1000100 6 using namespace std; 7 int n,k,tot,ans; 8 int st[M]; 9 struct point{int l,r,id;}a[M]; 10 struct Node{int id,v;}; 11 priority_queue<Node>q; 12 bool cmp(point a1,point a2) {return a1.l<a2.l;} 13 bool operator < (Node a1,Node a2) {return a1.v>a2.v;} 14 int main() 15 { 16 scanf("%d%d",&n,&k); 17 for(int i=1;i<=n;i++) 18 scanf("%d%d",&a[i].l,&a[i].r),a[i].id=i; 19 sort(a+1,a+1+n,cmp); 20 for(int i=1;i<=n;i++) 21 { 22 q.push((Node){a[i].id,a[i].r}); 23 while(q.top().v<a[i].l) q.pop(); 24 if(q.size()>k) q.pop(); 25 if(q.size()==k) ans=max(ans,q.top().v-a[i].l); 26 } 27 while(!q.empty()) q.pop(); 28 for(int i=1;i<=n;i++) 29 { 30 q.push((Node){a[i].id,a[i].r}); 31 while(q.top().v<a[i].l) q.pop(); 32 if(q.size()>k) q.pop(); 33 if(q.size()==k&&ans==q.top().v-a[i].l) 34 { 35 while(!q.empty()) 36 st[++tot]=q.top().id,q.pop(); 37 } 38 } 39 sort(st+1,st+1+k); 40 printf("%d\n",ans); 41 for(int i=1;i<=k;i++) printf("%d ",st[i]); 42 return 0; 43 }