P1712 [NOI2016]区间

题意

题目描述

在数轴上有 \(N\) 个闭区间 \([l_1,r_1],[l_2,r_2],...,[l_n,r_n]\) 。现在要从中选出 \(M\) 个区间,使得这 \(M\) 个区间共同包含至少一个位置。换句话说,就是使得存在一个 \(x\) ,使得对于每一个被选中的区间 \([l_i,r_i]\) ,都有 \(l_i \leq x \leq r_i\) 。

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

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

输入输出格式

输入格式:

第一行包含两个正整数 \(N,M\) 用空格隔开,意义如上文所述。保证 \(1 \leq M \leq N\)

接下来 \(N\) 行,每行表示一个区间,包含用空格隔开的两个整数 \(l_i\) 和 \(r_i\) 为该区间的左右端点。

\(N \leq 500000,M \leq 200000,0 \leq l_i \leq r_i \leq 10^9\)

输出格式:

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

输入输出样例

输入样例:

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

输出样例:

2

说明

思路

2018-10-6 非完美算法测试唯一的可做题,然后用 \(STL\) 瞎搞了一波,只有 \(60\) 分 \(qwq\) 。赛后学习了 logeadd 的代码,就 \(A\) 掉了。

首先按照区间长度排序,然后我们枚举排序后的 \([1,M]\) 的一段区间 \([L,R]\) ,使得这一段区间能够刚好覆盖住同一个点 \(m\) 次,那么就可以用 \(len[R]-len[L]\) 来更新答案。

枚举区间可以使用尺取法,而判断这一区间是否合法可以用线段树。对于每一个区间 \([l_i,r_i]\) ,我们在线段树上进行这个区间的区间加,然后统计区间最大值,就可以了。当然,这个数据范围是需要离散化的。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MAXN=5e5+5;
LL n,m,cnt,head,tail,ans=LLONG_MAX,s[MAXN],t[MAXN],num[MAXN<<1];
struct Segment
{
LL l,r,len;
bool operator < (const Segment &sjf) const {return len<sjf.len;}
}seg[MAXN];
struct SegmentTree
{
LL l,r,data,tag;
#define l(a) tree[a].l
#define r(a) tree[a].r
#define d(a) tree[a].data
#define t(a) tree[a].tag
}tree[MAXN<<3];
LL read()
{
LL re=0;
char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
return re;
}
void build(LL p,LL ll,LL rr)
{
l(p)=ll,r(p)=rr;
if(ll==rr) return ;
LL mid=(ll+rr)>>1;
build(p<<1,ll,mid);
build(p<<1|1,mid+1,rr);
}
void pushdown(LL p)
{
if(t(p))
{
d(p<<1)+=t(p),d(p<<1|1)+=t(p);
t(p<<1)+=t(p),t(p<<1|1)+=t(p);
t(p)=0;
}
}
void change(LL p,LL ll,LL rr,LL k)
{
if(ll<=l(p)&&r(p)<=rr)
{
t(p)+=k,d(p)+=k;
return ;
}
pushdown(p);
LL mid=(l(p)+r(p))>>1;
if(mid>=ll) change(p<<1,ll,rr,k);
if(mid<rr) change(p<<1|1,ll,rr,k);
d(p)=max(d(p<<1),d(p<<1|1));
}
int main()
{
n=read(),m=read();
for(LL i=1;i<=n;i++) num[cnt++]=seg[i].l=read(),num[cnt++]=seg[i].r=read(),seg[i].len=seg[i].r-seg[i].l;
sort(seg+1,seg+n+1);
sort(num,num+cnt);
cnt=unique(num,num+cnt)-num;
for(LL i=1;i<=n;i++) seg[i].l=lower_bound(num,num+cnt,seg[i].l)-num,seg[i].r=lower_bound(num,num+cnt,seg[i].r)-num;
build(1,0,cnt-1);
while(1)
{
while(d(1)<m&&tail<n)
{
tail++;
change(1,seg[tail].l,seg[tail].r,1);
}
if(d(1)<m) break;
while(d(1)>=m&&head<n)
{
head++;
change(1,seg[head].l,seg[head].r,-1);
}
ans=min(ans,seg[tail].len-seg[head].len);
}
printf("%lld",ans==LLONG_MAX?-1:ans);
return 0;
}

Luogu P1712 [NOI2016]区间(线段树)的更多相关文章

  1. 洛谷$P1712\ [NOI2016]$区间 线段树

    正解:线段树 解题报告: 传送门$QwQ$ $umm$很久以前做的了来补个题解$QwQ$ 考虑给每个区间按权值($r-l$从大往小排序,依次加入,然后考虑如果有一个位置被覆盖次数等于$m$了就可以把权 ...

  2. luogu P1712 [NOI2016]区间 贪心 尺取法 线段树 二分

    LINK:区间 没想到尺取法. 先说暴力 可以发现答案一定可以转换到端点处 所以在每个端点从小到大扫描线段就能得到答案 复杂度\(n\cdot m\) 再说我的做法 想到了二分 可以进行二分答案 从左 ...

  3. [NOI2016]区间 线段树

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

  4. UOJ222 NOI2016 区间 线段树+FIFO队列

    首先将区间按长度排序后离散化端点(这里的“长度”指的是离散化之前区间的实际长度) 然后模拟一个队列,区间按排好的顺序依次进入,直到某个点被覆盖了M次.之后依次出队,直到所有点都被覆盖小于M次 修改和询 ...

  5. BZOJ.4653.[NOI2016]区间(线段树)

    BZOJ4653 UOJ222 考虑二分.那么我们可以按区间长度从小到大枚举每个区间,对每个区间可以得到一个可用区间长度范围. 我们要求是否存在一个点被这些区间覆盖至少\(m\)次.这可以用线段树区间 ...

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

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

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

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

  8. luogu P1712 [NOI2016]区间

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

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

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

随机推荐

  1. Pyinstaller打包Web项目

    最近需要用python打包一个单页面网页demo,于是准备用python包pyinstaller来打包程序.网上搜索了一下,大部分教程都是打包非web项目,这里分享一下打包简单网页demo的过程. 系 ...

  2. java_新特性未整理

    得到的.className method.isAnnotationPresent:判断是否有指定的注解,注解.class method.invoke:执行 */}

  3. java笔试之求最大连续bit数

    功能: 求一个byte数字对应的二进制数字中1的最大连续数,例如3的二进制为00000011,最大连续2个1    输入: 一个byte型的数字    输出: 无     返回: 对应的二进制数字中1 ...

  4. telnet- Linux必学的60个命令

    1.作用 telnet表示开启终端机阶段作业,并登入远端主机.telnet是一个Linux命令,同时也是一个协议(远程登陆协议). 2.格式 telnet [-8acdEfFKLrx][-b][-e] ...

  5. NOIP2018游记 & 退役记

    NOIP2018游记 & 退役记 我是一名来自湖北武汉华中师大一附中的高二\(OIer\),学习\(OI\)一年,今年去参加\(NOIP\),然后退役.这是一篇\(NOIP2018\)的游记, ...

  6. Android开发 ViewPager删除Item后,不会更新数据和View

    问题描述: 在使用ViewPager的适配器删除适配器里一个Item后依然会,而删除的这个item依然会保留缓存,适配器不会重新加载更新数据.如下代码: public class TReleaseCi ...

  7. [JZOJ1320] 【Usaco2009 gold 】拯救奶牛

    题目 题目大意 一个三角形的网格图,三角形与其有共同边的三角形相连. 起点到所有终点的最短距离. 思考历程 数据看起来还挺大的,所以不是什么图论算法. 这显然是一个结论题. 什么结论? 然后我就开始推 ...

  8. Sentinel 发布里程碑版本,添加集群流控功能

    自去年10月底发布GA版本后,Sentinel在近期发布了另一个里程碑版本v1.4(最新的版本号是v1.4.1),加入了开发者关注的集群流控功能. 集群流控简介 为什么要使用集群流控呢?假设我们希望给 ...

  9. Flask从入门到入土

    一.flask介绍 Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对 ...

  10. EF实体模型的更新

    摘要 解决前期数据库优先添加的实体,然后数据库表结构发生变化后,导致代码操作EF插入更新数据失败问题 EF 数据库更新模型 相比大家在使用实体操作数据库的时候,都是采取数据库优先,手动添加实体模型.但 ...