首页 > 代码库 > 区间(bzoj 4653)
区间(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
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; }
区间(bzoj 4653)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。