BZOJ 4653: [Noi2016]区间 线段树
来源:互联网 发布:数据服务 编辑:程序博客网 时间:2024/06/05 17:09
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
题解
首先我们将所有区间按照长度排序,然后我们依次扫描每个区间,用线段树找到它第一次有点覆盖次数超过k的另一个区间,更新一下答案,因为左端点递增时右端点也一定递增,所以维护两个指针扫一下即可。
#include<cstdio>#include<cstdlib>#include<iostream>#include<iomanip>#include<cstring>#include<string>#include<algorithm>#include<ctime>#include<cmath>using namespace std;struct xianduan{ int l,r,maxx,lazy; void add(int val) { maxx+=val; lazy+=val; }}a[5000000];void make_tree(int o,int l,int r){ a[o].l=l; a[o].r=r; a[o].maxx=0; a[o].lazy=0; if(l==r) return; int mid=l+r>>1; make_tree(2*o,l,mid); make_tree(2*o+1,mid+1,r);}void push_down(int o){ if(a[o].l==a[o].r) return; if(!a[o].lazy) return; a[2*o].add(a[o].lazy); a[2*o+1].add(a[o].lazy); a[o].lazy=0;}void change(int o,int l,int r,int d){ if(a[o].r<l || a[o].l>r) return; push_down(o); if(a[o].l>=l && a[o].r<=r) { a[o].add(d); return; } change(2*o,l,r,d); change(2*o+1,l,r,d); a[o].maxx=max(a[2*o].maxx,a[2*o+1].maxx);}struct interval{ int l,r,val; bool operator < (interval b) const { return val<b.val; }}q[600000];int dd[1100000];int top=0;int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d%d",&q[i].l,&q[i].r),q[i].val=q[i].r-q[i].l+1,dd[++top]=q[i].l,dd[++top]=q[i].r; sort(dd+1,dd+1+top); top=unique(dd+1,dd+1+top)-dd-1; for(int i=1;i<=n;i++) q[i].l=lower_bound(dd+1,dd+1+top,q[i].l)-dd,q[i].r=lower_bound(dd+1,dd+1+top,q[i].r)-dd; sort(q+1,q+1+n); int r=1; int ans=2147483647; make_tree(1,1,top); for(int i=1;i<=n;i++) { while(a[1].maxx<m && r<=n) { change(1,q[r].l,q[r].r,1); r++; } if(a[1].maxx<m) break; ans=min(ans,q[r-1].val-q[i].val); change(1,q[i].l,q[i].r,-1); } if(ans==2147483647) cout<<-1; else cout<<ans<<endl; return 0;}
阅读全文
0 0
- bzoj 4653: [Noi2016]区间 线段树
- BZOJ 4653: [Noi2016]区间 线段树
- bzoj 4653: [Noi2016]区间 (线段树)
- bzoj 4653: [Noi2016]区间(尺取+线段树)
- BZOJ 4653: [Noi2016]区间
- BZOJ 4653: [Noi2016]区间
- bzoj 4653 [Noi2016]区间
- 【线段树】[NOI2016]区间
- [BZOJ4653][Noi2016]区间 线段树
- 【BZOJ4653】【NOI2016】区间 线段树
- 【NOI2016】区间(线段树+离散化)
- 4653: [Noi2016]区间
- NOI2016区间
- BZOJ 8843 染色 [树链剖分+区间线段树]
- BZOJ4653 [Noi2016]区间
- 【uoj222】 NOI2016—区间
- [NOI2016][bzoj4653]区间
- 【NOI2016】bzoj4653 区间
- Android布局动画
- echarts
- 刷清橙OJ--A1038.超级重复串
- 润乾报表单独部署url安全之加解密函数
- 程序员面试金典——奇偶位交换__(位运算)
- BZOJ 4653: [Noi2016]区间 线段树
- 翻转单词顺序
- 初识多线程 (其二)
- 类加载器
- 二阶构造
- MySQL和Oracle
- 1020. 月饼 (25)
- 单例模式+Java
- CSDN我又回来了