【bzoj4653】[Noi2016]区间

来源:互联网 发布:linux locale命令 编辑:程序博客网 时间:2024/05/21 02:53

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

题解
把线段从小到大排序,一次加入线段树中,知道存在某一点被覆盖m条线段,然后从小的开始删,知道不满足为止,这时即找到了一组解,重复此操作即可。需要离散。

代码

#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>struct node1{int l,r,al,ar,len,id;}a[500005];struct node2{int a,l,r,id;}ls[1000005];int add[8000005],mx[8000005];int n,m,cnt;using namespace std;inline int read(){    int x=0;char ch=getchar();    while (ch<'0'||ch>'9') ch=getchar();    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x;}bool cmp1(node1 a,node1 b){return a.len<b.len;}bool cmp2(node2 a,node2 b){return a.a<b.a;}void pushdown(int p,int l,int r){    if (l==r) return;    int mid=(l+r)>>1;    add[p<<1]+=add[p];add[p<<1|1]+=add[p];    mx[p<<1]+=add[p];mx[p<<1|1]+=add[p];    add[p]=0;}void modify(int p,int l,int r,int x,int y,int z){    if (add[p]) pushdown(p,l,r);    if (l==x&&r==y)    {        add[p]+=z;        mx[p]+=z;        return;    }    int mid=(l+r)>>1;    if (y<=mid) modify(p<<1,l,mid,x,y,z);    else if (x>mid) modify(p<<1|1,mid+1,r,x,y,z);    else    {        modify(p<<1,l,mid,x,mid,z);        modify(p<<1|1,mid+1,r,mid+1,y,z);    }    mx[p]=max(mx[p<<1],mx[p<<1|1]);}int main(){    n=read();m=read();    for (int i=1;i<=n;i++)    {        a[i].l=read();a[i].r=read();a[i].len=a[i].r-a[i].l;        ls[++cnt].a=a[i].l;        ls[cnt].l=1;        ls[cnt].id=i;        ls[++cnt].a=a[i].r;        ls[cnt].r=1;        ls[cnt].id=i;    }    sort(ls+1,ls+cnt+1,cmp2);    int pre=-1,num=0;    for (int i=1;i<=cnt;i++)    {        if (ls[i].a!=pre) pre=ls[i].a,num++;        if (ls[i].l) a[ls[i].id].al=num;        else a[ls[i].id].ar=num;    }    sort(a,a+n+1,cmp1);    int st=1,ed=1,ans=2000000000;    while (ed<=n)    {        while (mx[1]<m&&ed<=n)        {            modify(1,1,num,a[ed].al,a[ed].ar,1);            ed++;        }        while (mx[1]>=m)        {            ans=min(ans,a[ed-1].len-a[st].len);            modify(1,1,num,a[st].al,a[st].ar,-1);            st++;        }    }    if (ans==2000000000) puts("-1");    else cout<<ans;    return 0;}
0 0
原创粉丝点击