1. 程式人生 > >[BZOJ5102]Prawnicy

[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

Sample Output

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 }