目链接:http://uoj.ac/problem/222

在数轴上有 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】区间的更多相关文章

  1. BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针

    BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间, ...

  2. [Noi2016]区间[离散化+线段树维护+决策单调性]

    4653: [Noi2016]区间 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 621  Solved: 329[Submit][Status][D ...

  3. [NOI2016]区间 线段树

    [NOI2016]区间 LG传送门 考虑到这题的代价是最长边减最短边,可以先把边按长度排个序,双指针维护一个尺取的过程,如果存在包含某个点的区间数\(\ge m\),就更新答案并把左指针右移,这样做的 ...

  4. [BZOJ4653][NOI2016]区间 贪心+线段树

    4653: [Noi2016]区间 Time Limit: 60 Sec  Memory Limit: 256 MB Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],. ...

  5. 【BZOJ4653】[Noi2016]区间 双指针法+线段树

    [BZOJ4653][Noi2016]区间 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含 ...

  6. [NOI2016]区间 题解(决策单调性+线段树优化)

    4653: [Noi2016]区间 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1593  Solved: 869[Submit][Status][ ...

  7. Luogu P1712 [NOI2016]区间(线段树)

    P1712 [NOI2016]区间 题意 题目描述 在数轴上有 \(N\) 个闭区间 \([l_1,r_1],[l_2,r_2],...,[l_n,r_n]\) .现在要从中选出 \(M\) 个区间, ...

  8. 【题解】P1712 [NOI2016]区间(贪心+线段树)

    [题解]P1712 [NOI2016]区间(贪心+线段树) 一个observe是,对于一个合法的方案,将其线段长度按照从大到小排序后,他极差的来源是第一个和最后一个.或者说,读入的线段按照长度分类后, ...

  9. 洛谷P1712 [NOI2016]区间 尺取法+线段树+离散化

    洛谷P1712 [NOI2016]区间 noi2016第一题(大概是签到题吧,可我还是不会) 链接在这里 题面可以看链接: 先看题意 这么大的l,r,先来个离散化 很容易,我们可以想到一个结论 假设一 ...

  10. BZOJ4653: [Noi2016]区间

    传送门 UOJ上卡掉一个点,COGS上卡掉两个点..弃疗,不改了,反正BZOJ上过啦hhh 先把区间按长度递增排序.然后每次用线段树维护区间最大覆盖次数,用一个指针随便扫扫就行了. //NOI 201 ...

随机推荐

  1. 《杜增强讲Unity之Tanks坦克大战》8-子弹碰撞处理

    8 子弹碰撞处理 为了处理子弹打到坦克的伤害我们在这里新建一个Shell.cs 子弹有两种情况,碰到坦克炸开,没有碰到坦克则过2s子弹销毁. void Start () { Destroy (game ...

  2. 4. 为HelloWorld添加日志

    回顾 通过上篇内容,我们已经使用flask编写了我们的第一个接口或者说是html页面.我们可以看到,使用flask来编写接口/页面是十分简单的.那么接下来,我们丰富一下上面的例子. 需求 现在的需求来 ...

  3. .NetCore mvc Ajax Post数据到后端

    在前端页面中,如果没有表单,想把复杂对象提交到后端,可使用以下方法 后端Controller中定义以下方法: [HttpPost] public int AddSolution([FromBody]S ...

  4. MySQL基础练习(三)

    经过之前两次的学习,这次用MySQL进行略微复杂的操作练习 各部门工资最高的员工 首先创建表employee和表department.如下 我们需要查询每个部门工资最高的员工 select a.Nam ...

  5. c++虚继承与虚函数

    学习继承与多态时看到这两个概念,记录整理. 虚继承与虚函数都是用virtual关键字实现,虚继承为了防止多重继承,而虚函数为了实现多态. 是几个例子. 虚继承: class A{}; class B: ...

  6. Scrum Meeting 3 -2014.11.5

    这几天小伙伴们都在努力,研究出不少改进方案并加以设计和实施了,分词算法的优化进度可观,而其他的任务在改进的过程中产生了些问题,对于之前代码的设计感到疑惑,我们找到了上届的学长们咨询,他们也给出了不少建 ...

  7. 2017-2018-2 1723 『Java程序设计』课程 结对编程练习_四则运算 第二周

    一.结对对象 姓名:侯泽洋 学号:20172308 担任角色:驾驶员(侯泽洋) 伙伴第二周博客地址 二.本周内容 (一)继续编写上周未完成代码 1.本周继续编写代码,使代码支持分数类计算 2.相关过程 ...

  8. 用JAVA制作微型操作系统4月23日情况

    弄好了一个自认为十分精美的界面,但本想着昨天就在开始按钮上先套入控制jp222面板上的jb2标签上的时间更新,这按钮起到开始线程的作用(我认为按钮应该可以通过t.start()来触发线程,结果不知为什 ...

  9. gdb调试器学习链接

    首先要带 -g 选项用gcc编译 常用指令:http://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/gdb.html#gdb 带main的命令行参 ...

  10. java对文件的操作

    1.按字节读取文件内容2.按字符读取文件内容3.按行读取文件内容 4.随机读取文件内容 public class ReadFromFile {     /**      * 以字节为单位读取文件,常用 ...