题目描述

在数轴上有 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 为该区间的左右端点。
N<=500000,M<=200000,0≤li≤ri≤10^9

输出

只有一行,包含一个正整数,即最小花费。

样例输入

6 3
3 5
1 2
3 4
2 2
1 5
1 4

样例输出

2


题解

双指针法+线段树

这道傻*题我一开始竟然没看出来 = =

由于代价只跟最短和最长的区间长度有关,和区间个数无关,因此如果我们确定了一个最短的区间,那么可以依次寻找长度比它大的区间,直到找到答案或无论如何也找不到答案。

那么我们就可以将区间按照长度排序,并将区间端点离散化,枚举最短的区间使用线段树维护区间内被覆盖次数最多的点的被覆盖次数,直接维护区间最大值、区间修改就好了。

然后我们可以发现,随着最短区间的变化(即头指针的移动),答案最长区间(即尾指针)是单调不减的,所以可以使用双指针法来维护它。

时间复杂度$O(n\log n)$

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 500010
#define lson l , mid , x << 1
#define rson mid + 1 , r , x << 1 | 1
using namespace std;
struct data
{int l , r , len;
}a[N];
int v[N << 1] , maxn[N << 3] , add[N << 3];
bool cmp(data a , data b)
{return a.len < b.len;
}
void pushup(int x)
{maxn[x] = max(maxn[x << 1] , maxn[x << 1 | 1]);
}
void pushdown(int x)
{if(add[x]){maxn[x << 1] += add[x] , maxn[x << 1 | 1] += add[x];add[x << 1] += add[x] , add[x << 1 | 1] += add[x];add[x] = 0;}
}
void update(int b , int e , int a , int l , int r , int x)
{if(b <= l && r <= e){maxn[x] += a , add[x] += a;return;}pushdown(x);int mid = (l + r) >> 1;if(b <= mid) update(b , e , a , lson);if(e > mid) update(b , e , a , rson);pushup(x);
}
int main()
{int n , m , i , p = 0 , ans = 1 << 30;scanf("%d%d" , &n , &m);for(i = 1 ; i <= n ; i ++ ) scanf("%d%d" , &a[i].l , &a[i].r) , a[i].len = a[i].r - a[i].l , v[i] = a[i].l , v[i + n] = a[i].r;sort(a + 1 , a + n + 1 , cmp) , sort(v + 1 , v + 2 * n + 1);for(i = 1 ; i <= n ; i ++ ) a[i].l = lower_bound(v + 1 , v + 2 * n + 1 , a[i].l) - v , a[i].r = lower_bound(v + 1 , v + 2 * n + 1 , a[i].r) - v;for(i = 1 ; i <= n ; i ++ ){while(p < n && maxn[1] < m) p ++ , update(a[p].l , a[p].r , 1 , 1 , 2 * n , 1);if(maxn[1] < m) break;ans = min(ans , a[p].len - a[i].len);update(a[i].l , a[i].r , -1 , 1 , 2 * n , 1);}printf("%d\n" , ans == 1 << 30 ? -1 : ans);return 0;
}

转载于:https://www.cnblogs.com/GXZlegend/p/7128279.html

【bzoj4653】[Noi2016]区间 双指针法+线段树相关推荐

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

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

  2. 【BZOJ4653】区间,离散化+线段树

    Time:2016.08.09 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 当时打同步赛的时候 花了3h去做T3提答 大概玩了50分 回来看T1竟然是懵逼状态-- 想了一会,满脑 ...

  3. BZOJ4653: [Noi2016]区间(线段树 双指针)

    题意 题目链接 Sol 按照dls的说法,一般这一类的题有两种思路,一种是枚举一个点\(M\),然后check它能否成为答案.但是对于此题来说好像不好搞 另一种思路是枚举最小的区间长度是多少,这样我们 ...

  4. luogu P5142 区间方差(线段树、乘法逆元)

    luogu P5142 区间方差 本题要求维护模区间方差,很明显是一道数据结构题. 我们化简方差公式: 而平均数等于 可以发现,我们只需要维护序列的区间和和区间平方和,就可以维护平均数和方差. 区间和 ...

  5. 题解【bzoj4653 [NOI2016] 区间】

    先按照长度排个序,然后依次添加区间.什么是添加?设这个区间是\([l,r]\),添加就是把\(a_l,a_{l+1},a_{l+2},{...},a_{r}\)都加上\(1\),其中\(a_i\)表示 ...

  6. HDU 4553 约会安排 (区间合并)【线段树】

    <题目链接> 寒假来了,又到了小明和女神们约会的季节.  小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复"呵呵",所以,小明的最爱就是和女神们 ...

  7. P6327 区间加区间sin和 线段树 + 数学

    传送门 文章目录 题意: 思路: 题意: 给你一个长度为nnn的序列aaa,有mmm次操作,每次操作分两种类型: (1)l,r,v(1)l,r,v(1)l,r,v,将al,al+1,...,ara_l ...

  8. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

  9. BZOJ-1012[JSOI2008]最大数maxnumber 线段树区间最值

    这道题相对简单下面是题目: 1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec Memory Limit: 162 MB Submit: 6542 Solve ...

最新文章

  1. 系统升级到10.13之后cocoapods安装失败问题解决办法
  2. 五、redis和关系型数据库如何配合使用
  3. java读取ini_java 读取ini配置文件
  4. 浅谈稳压二极管的选用和使用条件--摘自:工程师飞燕
  5. Chrome新的语言API,让您的浏览器说话
  6. 安迈云加入GDCA全球分布式云联盟,携手业内共建新生态
  7. 解决默写浏览器中点击input输入框时,placeholder的值不消失的方法
  8. 架构之旅~一个操作的返回要有一个标准,看我的公用消息类
  9. javascript中一个字符占几个字节
  10. 第六十一期:中国农民花3000块,发明史上最牛输入法!曾火遍中国20年
  11. Apriori算法Matlab实现
  12. 怎么撰写一份优秀的数据分析报告(二)
  13. linux下常用alias
  14. 股票代码中OF与SZ的区别
  15. 【ARM】迅为rk3568开发板buildroot添加桌面应用
  16. Latex---IEEE论文写作
  17. 机器学习算法--分类的衡量指标(误差矩阵或混淆矩阵)
  18. 微信小程序在使用权限时,不弹弹框
  19. 51nod1820 长城之旅
  20. 试用多片2K×8的RAM扩展为4K×16的RAM(下面用多片1K×4的RAM扩展为2K×8的RAM代替之, 二者原理相同)(二〇二〇年山东大学数字电路906综合题第1题)(全网第一手资料)

热门文章

  1. python ftp编程_Python编程-FTP
  2. jconsole中无法显示本地启动的tomcat
  3. 觉得自己目前还很菜。
  4. .NET生成静态页面并分页
  5. python打印多个变量名_如何在Python中打印单个和多个变量?
  6. (转)Managed DirectX +C# 开发(入门篇)(五)
  7. 【java学习之路】(java SE篇)006.异常
  8. python跟我学_灞桥区跟我学python
  9. 服务端设置忽略更新_深入理解Kafka服务端之日志对象的读写数据流程
  10. Caused by: java.sql.SQLException: Unable to open a test connection to the given database报错无法打开到给定数据库