[BZOJ5102]Prawnicy
阿新 • • 發佈:2018-11-23
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
3 8
4 12
2 6
1 10
5 9
11 12
Sample Output
41 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) {returna1.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 }