區間(bzoj 4653)

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

Sample Output

2
/*
    不得不說,本弱是真弱啊,這道題的思路好像不是很難,可是就是想不出。
    首先將區間離散化,而後按照區間長度排序,一種暴力的方法是枚舉左區間,而後枚舉用線段樹斷定找到第一個知足條件的右區間,這樣的方法是O(n^2logn)的。
    其實咱們能夠發現對於遞增的左區間來講,第一個知足條件的右區間也是遞增的,這樣複雜度就降到了O(nlogn)。 
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 500010
#define inf 1000000000
using namespace std;
int b[N*2],n,m;
int mx[N*8],tag[N*8];
struct node{int l,r,len;}a[N];
bool cmp(const node&x,const node&y){return x.len<y.len;}

void push_up(int k){
    mx[k]=max(mx[k*2],mx[k*2+1]);
}
void push_down(int k){
    if(!tag[k]) return;
    mx[k*2]+=tag[k];
    tag[k*2]+=tag[k];
    mx[k*2+1]+=tag[k];
    tag[k*2+1]+=tag[k];
    tag[k]=0;
}
void add(int k,int l,int r,int x,int y,int val){
    if(l>=x&&r<=y){
        mx[k]+=val;
        tag[k]+=val;
        return;
    }
    push_down(k);
    int mid=l+r>>1;
    if(x<=mid) add(k*2,l,mid,x,y,val);
    if(y>mid) add(k*2+1,mid+1,r,x,y,val);
    push_up(k);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&a[i].l,&a[i].r);
        a[i].len=a[i].r-a[i].l;
        b[i*2-1]=a[i].l;
        b[i*2]=a[i].r;
    }
    sort(b+1,b+n*2+1);
    int tot=unique(b+1,b+2*n+1)-b-1;
    for(int i=1;i<=n;i++){
        a[i].l=lower_bound(b+1,b+tot+1,a[i].l)-b;
        a[i].r=lower_bound(b+1,b+tot+1,a[i].r)-b;
    }
    sort(a+1,a+n+1,cmp);
    int tt=1,ans=inf;
    for(int i=1;i<=n;i++){
        while(mx[1]<m&&tt<=n){
            add(1,1,tot,a[tt].l,a[tt].r,1);
            tt++;
        }
        if(mx[1]>=m) ans=min(ans,a[tt-1].len-a[i].len);
        add(1,1,tot,a[i].l,a[i].r,-1);
    }
    if(ans!=inf) printf("%d",ans);
    else printf("-1");
    return 0;
}
相關文章
相關標籤/搜索