BZOJ4653: [Noi2016]区间

Time Limit: 60 Sec  Memory Limit: 256 MB
Submit: 1646  Solved: 898
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


离散化+按长度排序并以线段树的方式更新覆盖+更新答案即可

 
 

/**************************************************************

    Problem: 4653

    User: ictsing

    Language: C++

    Result: Accepted

    Time:11276 ms

    Memory:67704 kb

****************************************************************/

 

//BZOJ4653 [Noi2016]区间

#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

const int mt = 1000000+5;

struct qwq{

    int x,id;

}p[mt<<1];

struct ques{

    int l,r,len;

}q[mt];

int h[mt<<1];

bool cmp(qwq a,qwq b)

{

    return a.x<b.x;

}

bool cmpp(ques a,ques b)

{

    return a.len<b.len;

}

int tree[mt<<2];

int add[mt<<2];

inline int read()

{

    int num=0,flag=1;

    char ch;

    do{

       ch=getchar();

       if(ch=='-') flag=-1;

    }while(ch<'0'||ch>'9');

    do{

       num=num*10+ch-'0';

       ch=getchar();

    }while(ch>='0'&&ch<='9');

    return num*flag;

}

void pushup(int rt)

{

    if(rt)

    {

        tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);

    }

}

void pushdown(int rt)

{

    if(rt&&add[rt])

    {

        add[rt<<1]+=add[rt];

        add[rt<<1|1]+=add[rt];

        tree[rt<<1]+=add[rt];

        tree[rt<<1|1]+=add[rt];

        add[rt]=0;

    }

}

void update(int rt,int l,int r,int lft,int rgt,int val)

{

    if(lft<=l&&r<=rgt)

    {

        add[rt]+=val;

        tree[rt]+=val;

        return ;

    }

    pushdown(rt);

    int mid=(l+r)>>1;

    if(lft<=mid) update(rt<<1,l,mid,lft,rgt,val);

    if(rgt>mid) update(rt<<1|1,mid+1,r,lft,rgt,val);

    pushup(rt);

}

int main()

{

    int n=read(),m=read();

    for(int i=1;i<=n;i++)

        p[2*i-1].x=read(),p[2*i].x=read(),p[i*2-1].id=2*i-1,p[i*2].id=i*2,q[i].len=p[i*2].x-p[i*2-1].x;

    sort(p+1,p+2*n+1,cmp);

    int k=0;

    for(int i=1;i<=2*n;i++)

    {

        if(p[i].x==p[i-1].x) h[p[i].id]=k;

        else h[p[i].id]=++k;

    }

    for(int i=1;i<=n;i++)

    {

        q[i].l=h[2*i-1],q[i].r=h[2*i];

    }

    sort(q+1,q+n+1,cmpp);

    int point=0;

    int ans=2e9;

    for(int i=1;i<=n;i++)

    {

        //cout<<q[i].l<<" "<<q[i].r<<" "<<point<<endl;

        //cout<<tree[1]<<endl;

        while(point<n&&tree[1]<m)

        {

            point++;

            update(1,1,k,q[point].l,q[point].r,1);

            //cout<<tree[1]<<" qwq "<<endl;

        }

        if(tree[1]>=m) 

        {

            ans=min(ans,q[point].len-q[i].len);

        }       

        update(1,1,k,q[i].l,q[i].r,-1);

    }

    if(ans!=2e9) printf("%d\n",ans);

    else puts("-1");

    return 0;

}

 

评论

热度(6)