原题传送门

Description

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

对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。

求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。

Input

第一行包含两个正整数 n,m用空格隔开,意义如上文所述。

接下来 n行,每行表示一个区间,包含用空格隔开的两个整数 li 和 ri 为该区间的左右端点。

Output

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

Sample Input

6 3

3 5

1 2

3 4

2 2

1 5

1 4

Sample Output

2

Hint

保证 1≤m≤n,N<=500000,M<=200000,0≤li≤ri≤10^9

Time Limit : 3s ,Memory Limit: 256MB.

Solution

首先考虑如何处理区间共同包含至少一个位置这一问题,显然可以利用线段树来解决,由于区间范围较大,因此需要离散后处理。

接下来考虑最长区间长度减去选中的最短区间长度,并且挑选m个,这一问题,根据最长-最短这一性质,以及数据范围,容易推断出将区间按长度排序后,利用头尾指针进行维护,将其间的所有区间加入线段树,只需要判断是否存在点被覆盖不少于m次的情况即可。

时间效率$ O(n \log_{2} n) $.

Code

#include <stdio.h>
#include <algorithm>
#define MN 500005
#define M (1<<20)
#define R register
#define mid (l+r>>1)
#define inf 0x3f3f3f3f
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read(){
R int x; R bool f; R char c;
for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
return f?-x:x;
}
int l[MN],r[MN],len[MN],T[M<<1],mark[M<<1],m,n,rk[MN],val[MN<<1],cnt=1,ans=inf;
inline bool cmp(int a,int b){return len[a]>len[b];}
inline int findpos(int k){
R int l=1,r=cnt; while(l<r)
if (val[mid]<k) l=mid+1;
else r=mid; return l;
}
inline void add(int k,int p){T[k]+=p,mark[k]+=p;}
inline void pushdown(int k){if (!mark[k]) return;add(k<<1,mark[k]);add(k<<1|1,mark[k]);mark[k]=0;}
inline void modify(int k,int l,int r,int a,int b,int ad){
if (l>=a&&r<=b) {add(k,ad); return;};pushdown(k);
if (a<=mid) modify(k<<1,l,mid,a,b,ad);
if (b>mid) modify(k<<1|1,mid+1,r,a,b,ad);
T[k]=max(T[k<<1],T[k<<1|1]);
}
int main(){
n=read(),m=read();
for (R int i=1; i<=n; ++i) l[i]=read(),r[i]=read(),len[i]=r[i]-l[i],rk[i]=i,val[(i-1)<<1|1]=l[i],val[i<<1]=r[i];
std::sort(val+1,val+(n<<1)+1);std::sort(rk+1,rk+n+1,cmp);
for (R int i=2; i<=(n<<1); ++i) if (val[i]!=val[i-1]) val[++cnt]=val[i];
for (R int i=1; i<=n; ++i) l[i]=findpos(l[i]),r[i]=findpos(r[i]);
for (R int h=1,t=1; t<=n; ++t)
for (modify(1,1,cnt,l[rk[t]],r[rk[t]],1); T[1]>=m; ans=min(ans,len[rk[h]]-len[rk[t]]),modify(1,1,cnt,l[rk[h]],r[rk[h++]],-1));
printf("%d\n",(ans==inf)?-1:ans);return 0;
}

【BZOJ4653】【Noi2016D2】区间的更多相关文章

  1. 【BZOJ-4653】区间 线段树 + 排序 + 离散化

    4653: [Noi2016]区间 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 107  Solved: 70[Submit][Status][Di ...

  2. BZOJ4653: [Noi2016]区间

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

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

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

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

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

  5. BZOJ4653:[NOI2016]区间(线段树)

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

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

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

  7. BZOJ4653 [NOI2016]区间 [线段树,离散化]

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

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

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

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

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

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

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

随机推荐

  1. C/C++生成随机数

    一.rand和srand   在C++11标准出来之前,C/C++都依赖于stdlib.h头文件的rand或者srand来生成随机数.   其不是真正的随机数,是一个伪随机数,是根据一个数(我们可以称 ...

  2. 每日冲刺报告——Day1(Java-Team)

    第一天报告(11.2  周四) 团队:Java-Team 成员: 章辉宇(284) 吴政楠(286) 陈阳(PM:288) 韩华颂(142) 胡志权(143) github地址:https://git ...

  3. mongodb 集群分片

    分片 在Mongodb里面存在另一种集群,就是分片技术,可以满足MongoDB数据量大量增长的需求 当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量,这 ...

  4. css精简命名

    想写写前言啥的,发现自己是前言无能星人. 简单吐吐槽好了,来到新公司,接手公司之前的项目,我想着也就是改改bug,慢慢来吧,粗略看了看这个项目的代码,目前仅看了html和css样式的,忍不住吐血三升. ...

  5. 服务器数据恢复方法_存储raid硬盘离线数据恢复案例

    [故障描述]某法院的一台HP-P4500的存储系统,底层是12块1TB的硬盘组的RAID.其中每6个1TB的盘一组,第一组的前面一部分组了一个RAID0+1,是存放HP-P4500嵌入式系统,接着组了 ...

  6. 让linux远程主机在后台运行脚本

    后台挂起:python xxx.py & 在脚本命令后面加入"&"符号就可以后台运行.结束进程:kill -9 sidps -ef | grep ... 查询sid

  7. Mego开发文档 - 建模高级主题

    建模高级主题 在建模过程中我们还有许多其他情况,这里列出本框架中的有用特性来用于解决此类问题. 函数映射 我们可以将指定的CLR函数映射到数据库中的系统函数或自定义函数,该特性用于补充框架中未提供的数 ...

  8. python学习之路01

    python自己也自学过一段时间了,看过视频,也买过几本基础的书来看,目前为止对于一些简单的代码还是可以看懂,但是自己总是觉得缺少些什么,可能是缺少系统化的学习,也可能是缺少实际项目经验,对于这些缺少 ...

  9. jodatime 时间比较

    public ArrayList<CalcPeriod> getCalcPeriods() { DateTime now = DateTime.now(); DateTime.Proper ...

  10. 两个activity的3D翻转动画.md

    一.业务需求 这里在公司项目设计时,用到了一个小的需求,就是点击一个按钮然后整个activity的页面进行3d翻转; 二.设计思路 由于是2个activity的之间的翻转动画,就意味着前90度是A页面 ...