4653: [Noi2016]区间

Time Limit: 60 Sec  Memory Limit: 256 MB

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
 
题解:
拿到这个题,应该都有一种贪心的冲动
但是贪心贪的好不好就决定了能不能过……
我们先拿一棵线段树来维护区间加和全局最大值操作,
添加线段转化为区间+1,当全局最大值>=m时,我们就找到了一组合法解:虽然我们不知道到底是谁,但全局最大值已经>=m,线段集合中对应的m条线段就是合法解
现在问题就变成了找谁是合法解。
把线段按照长度排序,那么我们按照顺序添加这些线段,如果找到一组最优解,就先把找到的线段集合中最大值看成选择的最后那条线段,最小值看成第一条线段,然后把最小值向右逼近,看能不能更优,这样O(n)扫一遍,同时一直记录合法解的最小值,就能找到最后的答案了!
代码见下:
 #include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
using namespace std;
const int N=,inf=0x7fffffff;
map<int,int> mp;
int stack[N<<],top,cnt,n,m;
struct line{int l,r,len;}seg[N];
inline bool mt(const line &a,const line &b){return a.len<b.len;}
struct node
{
node *ch[];int maxn,mark;
node(){ch[]=ch[]=NULL;mark=maxn=;}
inline void update(){maxn=max(ch[]->maxn,ch[]->maxn)+mark;}
}*null=new node(),*root=null;
inline node* newnode()
{
node *o=new node();
o->maxn=o->mark=;
o->ch[]=o->ch[]=null;
return o;
}
inline void add(node *&rt,int l,int r,int L,int R,int val)
{
if(rt==null)rt=newnode();
if(L<=l&&r<=R){rt->maxn+=val,rt->mark+=val;return;}
int mi=(l+r)>>;
if(L<=mi)add(rt->ch[],l,mi,L,R,val);
if(mi<R)add(rt->ch[],mi+,r,L,R,val);
rt->update();
}
int main()
{
scanf("%d%d",&n,&m);int ans=inf;
for(int i=;i<=n;i++)
{
scanf("%d%d",&seg[i].l,&seg[i].r);
seg[i].len=seg[i].r-seg[i].l;
stack[++top]=seg[i].l,stack[++top]=seg[i].r;
}
sort(stack+,stack+top+);stack[]=-inf;
for(int i=;i<=top;i++)
if(stack[i]!=stack[i-])mp[stack[i]]=++cnt;
for(int i=;i<=n;i++)seg[i].l=mp[seg[i].l],seg[i].r=mp[seg[i].r];
sort(seg+,seg+n+,mt);root=newnode();
for(int i=,j=;i<=n;i++)
{
add(root,,cnt,seg[i].l,seg[i].r,);
while(root->maxn>=m)
{
ans=min(ans,seg[i].len-seg[j].len);
add(root,,cnt,seg[j].l,seg[j].r,-);
j++;
}
}
printf("%d\n",(ans==inf)?-:ans);
}

[BZOJ4653][NOI2016]区间 贪心+线段树的更多相关文章

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

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

  2. BZOJ4653 [NOI2016] 区间 【线段树】

    题目分析: 首先思考一个二分答案的做法.我们可以注意到答案具有单调性,所以可以二分答案. 假设当前二分的答案是$ k $.那么按照大小顺序插入每个区间,同时在末端删除会对答案产生影响的区间.这里不妨用 ...

  3. 2018.08.17 bzoj4653: [Noi2016]区间(线段树+尺取法)

    传送门 将坐标离散化之后直接用尺取法(双指针)+线段树维护. 其实就是说只要目前所有点的被覆盖次数是大于等于m的就移动左指针删除区间更新答案,否则移动右指针加入区间更新答案. 话说忘记排序以及建树的时 ...

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

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

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

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

  6. 【洛谷 P1712】 [NOI2016]区间 (线段树+尺取)

    题目链接 emmm看起来好像无从下手, \(l_i,r_i\)这么大,肯定是要离散化的. 然后我们是选\(m\)个区间,我们先对这些区间按长度排个序也不影响. 排序后,设我们取的\(m\)个区间的编号 ...

  7. NOI2016 区间 【线段树】

    题目 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一个被 ...

  8. 洛谷 P1712 [NOI2016]区间(线段树)

    传送门 考虑将所有的区间按长度排序 考虑怎么判断点被多少区间覆盖,这个可以离散化之后用一棵权值线段树来搞 然后维护两个指针$l,r$,当被覆盖次数最多的点的覆盖次数小于$m$时不断右移$r$,在覆盖次 ...

  9. BZOJ4653(区间离散化+线段树+决策单调尺取)

    写得很好的题解 一眼过去很像是:排序,然后从前向后扫,有这个区间时插到树里,过去以后再删除.然后事实也是这样做的…… 具体起来: 1.如果考虑暴力的话,一种想法是枚举左端和右端要选取的区间(如果我们按 ...

随机推荐

  1. JS的发布订阅模式

    JS的发布订阅模式 这里要说明一下什么是发布-订阅模式 发布-订阅模式里面包含了三个模块,发布者,订阅者和处理中心.这里处理中心相当于报刊办事大厅.发布者相当与某个杂志负责人,他来中心这注册一个的杂志 ...

  2. python的种类

    Cpython     Python的官方版本,使用C语言实现,使用最为广泛,CPython实现会将源文件(py文件)转换成字节码文件(pyc文件),然后运行在Python虚拟机上. Jyhton   ...

  3. linux、WINDOWS命令行下查找和统计行数

    linux : 例子: netstat -an | grep TIME_WAIT | wc -l |  管道符 grep 查找命令 wc 统计命令 windows: 例子: netstat -an | ...

  4. testNG-失败用例重跑机制

    下面简单介绍下testNG的失败重跑的实现方法: 1.首先编写一个类,实现IRetryAnalyzer类,重写其中的retry方法. public class TestNGRetry implemen ...

  5. Android测试入门学习

    一,Android测试新人练习——安装及文件传输 [课前准备] Android测试环境搭建 1.下载并安装JDK: http://www.oracle.com/technetwork/java/jav ...

  6. shell 判断日期间隔及润年

    #!/bin/bash test.sh until echo "----------------------------------" echo "请输入您的选择:&qu ...

  7. sqli-labs学习笔记 DAY3

    DAY 3 sqli-labs lesson 6 同lesson 5,只是把单引号改为双引号 sqli-labs lesson 7 同lesson 5,只是把单引号后面加两个空格,使用Burpsuit ...

  8. 基于C#的机器学习--颜色混合-自组织映射和弹性神经网络

    自组织映射和弹性神经网络 自组织映射(SOM),或者你们可能听说过的Kohonen映射,是自组织神经网络的基本类型之一.自组织的能力提供了对以前不可见的输入数据的适应性.它被理论化为最自然的学习方式之 ...

  9. Python3 迭代器和生成器

    想要搞明白什么是迭代器,首先要了解几个名词:容器(container).迭代(iteration).可迭代对象(iterable).迭代器(iterator).生成器(generator). 看图是不 ...

  10. B. Counting-out Rhyme(约瑟夫环)

    Description n children are standing in a circle and playing the counting-out game. Children are numb ...