原题传送门

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. Ubuntu下安装gsoap

    昨天在ubuntu下进行安装gSOAP,费了很多时间,没成功,今天又来找了大量教程资料,终于一次成功,这里写下自己的安装步骤和方法,供大家参考. 首先下载gsoap,我下载的是gsoap-2.8.1. ...

  2. Ubuntu登陆密码忘记

    在VMware中安装了Ubuntu 10.04,经过了一段时间,再次登录的时候居然进不去了, 一开始不知道怎样在虚拟机中进入到Grub启动界面,网上搜索了一番,按照以下步骤重新为用户设定了新密码. 重 ...

  3. Autowired注解

    package com.how2java.pojo; import org.springframework.beans.factory.annotation.Autowired; public cla ...

  4. windows 7 netsh wlan命令连接wifi

    显示本机保存的profiles,配置文件是以wifi的ssid命名的. netsh wlan show profiles 用netsh wlan connect name=00_1111 连接其中一个 ...

  5. 用anaconda安装最新的TensorFlow版本

    Google发布了TensorFlow1.4正式版 在anaconad搜索依旧是1.2的版本,通过一番查阅,找到了方法 1,打开anaconda-prompt 2,激活你要安装的环境 activate ...

  6. B树和B+树的插入、删除图文详解

    简介:本文主要介绍了B树和B+树的插入.删除操作.写这篇博客的目的是发现没有相关博客以举例的方式详细介绍B+树的相关操作,由于自身对某些细节也感到很迷惑,通过查阅相关资料,对B+树的操作有所顿悟,写下 ...

  7. tomcat 修改默认字符集

    找到connector节点,插入 disableUploadTimeout="true" useBodyEncodingForURI="true" URIEnc ...

  8. OpendID是什么?

    一.OpenID的概念 1.问题的提出 2.OpenID是什么? 3.规范演进 二.OpenID 的运行原理 1.参与者 2.运行原理 3.典型场景 4.开源实现 5.优点&缺点 优点:   ...

  9. Spring Security 入门(1-8)Spring Security 的配置文件举例

  10. android studio 何如修改报名

    1. 重命名办法,网上很多见 2. 对于需要重新修改包名的级别的 a. 修改package 和 gradle 的包名,对应一致. b. 修改R 所在包名,使用crtl+n修改R文件的路径 c. 手动首 ...