【NOI2016】区间
在数轴上有 n 个闭区间 [l1,r1],[l2,r2],...,[ln,rn]。现在要从中选出 m 个区间,使得这 m 个区间共同包含至少一个位置。换句话说,就是使得存在一个 x ,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。
对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri]的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。
求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1 。
输入格式
第一行包含两个正整数 n,m,用空格隔开,意义如上文所述。保证 1≤m≤n。
接下来 n 行,每行表示一个区间,包含用空格隔开的两个整数 li 和 ri 为该区间的左右端点。
输出格式
只有一行,包含一个正整数,即最小花费。
样例一
input
6 3
3 5
1 2
3 4
2 2
1 5
1 4
output
2
explanation
如图,当 n=6, m=3n=6, m=3 时,花费最小的方案是选取 [3,5][3,5] 、[3,4][3,4] 、[1,4][1,4] 这三个区间,他们共同包含了 44 这个位置,所以是合法的。其中最长的区间是 [1,4][1,4] ,最短的区间是 [3,4][3,4] ,所以它的花费是 (4−1)−(4−3)=2(4−1)−(4−3)=2 。
限制与约定
所有测试数据的范围和特点如下表所示:
测试点编号 | n | m | li,ri |
---|---|---|---|
1 | 20 | 9 | 0≤li≤ri≤1000 |
2 | 10 | ||
3 | 199 | 3 | 0≤li≤ri≤100000 |
4 | 200 | ||
5 | 1000 | 2 | |
6 | 2000 | ||
7 | 199 | 60 | 0≤li≤ri≤5000 |
8 | 200 | 50 | |
9 | 0≤li≤ri≤10^9 | ||
10 | 1999 | 500 | 0≤li≤ri≤5000 |
11 | 2000 | 400 | |
12 | 500 | 0≤li≤ri≤10^9 | |
13 | 30000 | 2000 | 0≤li≤ri≤100000 |
14 | 40000 | 1000 | |
15 | 50000 | 15000 | |
16 | 100000 | 20000 | |
17 | 200000 | 0≤li≤ri≤10^9 | |
18 | 300000 | 50000 | |
19 | 400000 | 90000 | |
20 | 500000 | 200000 |
时间限制:3s
空间限制:256MB
题解
首先对li,ri离散化。
如样例
3 5
1 2
3 4
2 2
1 5
1 4
经排序后——1 1 1 2 2 2 3 3 4 4 5 5。(3,5)就变成了(7,11)这样l,r就变成<=500000了。
将每条线段按长度排个序,变成!
2 2
1 2
3 4
3 5
1 4
1 5
接下来,维护一个双指针(two pointer)如
l
1 2 3 4 5 6(线段编号)
r
不断向右移动r直到有个点出现的次数>m为止如
l
1 2 3 4 5 6
r——>r
记录答案
再不断向右移动l,直到没有一个位置出现的次数>m如
l—->l
1 2 3 4 5 6
r——>r
记录答案,以此类推,直到r>n为止。
放代码跑
- #include <cstdio>
- #include <algorithm>
- using namespace std;
- struct data{int l,r,len;}a[];
- struct tree{int l,r,max,lazy;}T[];
- int b[],num,i,j,k,n,m,x,y,t;
- bool cmp(const data&a,const data&b){return a.len<b.len;}
- int find(int x){
- int l=,r=num,ans;
- while (l<=r){
- int mid=(l+r)>>;
- if (b[mid]>=x)ans=mid,r=mid-;else l=mid+;
- }
- return ans;
- }
- void build(int i,int l,int r){
- T[i].l=l;T[i].r=r;T[i].max=;
- if (l==r)return;
- build(i*,l,(l+r)>>);build(i*+,((l+r)>>)+,r);
- }
- void pushdown(int i){
- if (T[i].lazy){
- T[i*].max+=T[i].lazy;T[i*+].max+=T[i].lazy;
- T[i*].lazy+=T[i].lazy;T[i*+].lazy+=T[i].lazy;
- T[i].lazy=;
- }
- }
- void pushup(int i){T[i].max=max(T[i*].max,T[i*+].max);}
- void change(int i,int l,int r,int v){
- if (T[i].l==l&&T[i].r==r){T[i].max+=v;T[i].lazy+=v;return;}
- pushdown(i);
- int mid=(T[i].l+T[i].r)>>;
- if (r<=mid)change(i*,l,r,v);
- else if (l>mid)change(i*+,l,r,v);
- else {change(i*,l,mid,v);change(i*+,mid+,r,v);}
- pushup(i);
- }
- int main(){
- scanf("%d%d",&n,&m);
- for (i=;i<=n;i++){
- scanf("%d%d",&x,&y);
- a[i].l=x;a[i].r=y;a[i].len=y-x;
- b[++num]=x;b[++num]=y;
- }
- sort(a+,a++n,cmp);sort(b+,b++num);
- for (i=;i<=n;i++)a[i].l=find(a[i].l),a[i].r=find(a[i].r);
- build(,,num);
- int l=,r=,ans=;
- while(l<=n&&r<=n){
- while (T[].max<m&&r<=n){change(,a[r].l,a[r].r,);r++;}
- if (T[].max>=m)ans=min(ans,a[r-].len-a[l].len);
- if (r>n)break;
- change(,a[l].l,a[l].r,-);l++;
- }
- printf("%d\n",ans==?-:ans);
- return ;
- }
【NOI2016】区间的更多相关文章
- BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针
BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间, ...
- [Noi2016]区间[离散化+线段树维护+决策单调性]
4653: [Noi2016]区间 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 621 Solved: 329[Submit][Status][D ...
- [NOI2016]区间 线段树
[NOI2016]区间 LG传送门 考虑到这题的代价是最长边减最短边,可以先把边按长度排个序,双指针维护一个尺取的过程,如果存在包含某个点的区间数\(\ge m\),就更新答案并把左指针右移,这样做的 ...
- [BZOJ4653][NOI2016]区间 贪心+线段树
4653: [Noi2016]区间 Time Limit: 60 Sec Memory Limit: 256 MB Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],. ...
- 【BZOJ4653】[Noi2016]区间 双指针法+线段树
[BZOJ4653][Noi2016]区间 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含 ...
- [NOI2016]区间 题解(决策单调性+线段树优化)
4653: [Noi2016]区间 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1593 Solved: 869[Submit][Status][ ...
- Luogu P1712 [NOI2016]区间(线段树)
P1712 [NOI2016]区间 题意 题目描述 在数轴上有 \(N\) 个闭区间 \([l_1,r_1],[l_2,r_2],...,[l_n,r_n]\) .现在要从中选出 \(M\) 个区间, ...
- 【题解】P1712 [NOI2016]区间(贪心+线段树)
[题解]P1712 [NOI2016]区间(贪心+线段树) 一个observe是,对于一个合法的方案,将其线段长度按照从大到小排序后,他极差的来源是第一个和最后一个.或者说,读入的线段按照长度分类后, ...
- 洛谷P1712 [NOI2016]区间 尺取法+线段树+离散化
洛谷P1712 [NOI2016]区间 noi2016第一题(大概是签到题吧,可我还是不会) 链接在这里 题面可以看链接: 先看题意 这么大的l,r,先来个离散化 很容易,我们可以想到一个结论 假设一 ...
- BZOJ4653: [Noi2016]区间
传送门 UOJ上卡掉一个点,COGS上卡掉两个点..弃疗,不改了,反正BZOJ上过啦hhh 先把区间按长度递增排序.然后每次用线段树维护区间最大覆盖次数,用一个指针随便扫扫就行了. //NOI 201 ...
随机推荐
- MOD 模除运算符
用于奇数和偶数的校验,星期几的计算,以及其它专门的计算.
- 使用request+Beautiful爬取妹子图
一.request安装 pip install requests request使用示例 import requests response = requests.get('https://www.mz ...
- WebGL2系列之实例数组(Instanced Arrays)
实例化数组 实例化是一种只调用一次渲染函数却能绘制出很多物体的技术,它节省渲染一个物体时从CPU到GPU的通信时间.实例数组是这样的一个对象,使用它,可以把原来的的uniform变量转换成attrib ...
- 解决网速慢时maven仓库访问慢
构建maven项目时会下载很多依赖,会从官网地址下载是个外国网站,访问速度会很慢,但可以通过修改maven的settings.xml文件换成国内的镜像地址就可以加快访问速度: 一.找到settings ...
- codeforces 1140E Palindrome-less Arrays
题目链接:http://codeforces.com/contest/1140/problem/E 题目大意: 如果一个数组的存在一个奇数长的回文就不好. 不是不好的数组是好的. 你可以把-1用1到k ...
- BP神经网络算法推导
目录 前置知识 梯度下降法 激活函数 多元复合函数求偏导的相关知识 正向计算 符号定义 输入层 隐含层 输出层 误差函数 反向传播 输出层与隐含层之间的权值调整 隐含层与输入层之间权值的调整 计算步骤 ...
- Ajax中post后台.net MVC中Controller的路径问题。
今天使用ajax的post方法,去访问mvc的controller,url的传值是 "//ProductCatalog/PostShareInfo",发现无论如何都访问不到. 我实 ...
- C++ Style Languages: C++, Objective-C, Java, C#
Hyperpolyglot.org From Hyperpolyglot.org C++ Style Languages: C++, Objective-C, Java, C# a side-by-s ...
- Scrum Meeting 10.23
Scrum Meeting No.3 今天所完成的任务仍然停留在学习基础知识上.说实话,由于缺少安卓开发.web开发的经验,我们只能一步步摸索着来. 成员 已完成任务 下一阶段任务 徐越 阅读网上的博 ...
- Week2-作业一——《构建之法》三章精读之想
Week2-作业一——精读<构建之法> 前言 其实我本人是不经常看书的,电子书倒是看了不少,实体书真的不经常看,但是为了这次作业的需求,我还是选择静下心来阅读一下这本<构建之法> ...