题目描述

在数轴上有 NN 个闭区间 [l_1,r_1],[l_2,r_2],...,[l_n,r_n][l1​,r1​],[l2​,r2​],...,[ln​,rn​] 。现在要从中选出 MM 个区间,使得这 MM 个区间共同包含至少一个位置。换句话说,就是使得存在一个 xx ,使得对于每一个被选中的区间 [l_i,r_i][li​,ri​] ,都有 l_i≤x≤r_ili​≤x≤ri​ 。

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

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

输入输出格式

输入格式:

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

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

N<=500000,M<=200000,0≤li≤ri≤10^9N<=500000,M<=200000,0≤li≤ri≤109

输出格式:

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

输入输出样例

输入样例#1:

  1. 6 3
  2. 3 5
  3. 1 2
  4. 3 4
  5. 2 2
  6. 1 5
  7. 1 4
输出样例#1:

  1. 2

说明

Solution:

  今天PKU学长HRZ讲课,说到了本题,然后思路比较巧妙。

  方法就是对区间离散后,按原长度从小到大排序,然后用一个队列维护两个指针$l,r$,$O(n)$的去加入区间$s[l,r]+=1$,用线段树维护区间最大值,若区间最大值$\geq m$则从前往后把加入的区间删除,直到区间最大值刚好$< m$,那么用$l-1$所保存的长度和当前加入的区间长度差去更新答案,然后就没了。

代码:

  1. #include<bits/stdc++.h>
  2. #define il inline
  3. #define ll long long
  4. #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
  5. #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
  6. #define lson l,m,rt<<1
  7. #define rson m+1,r,rt<<1|1
  8. using namespace std;
  9. const int N=;
  10. int n,m,maxn[N<<],add[N<<],ans=0x7fffffff;
  11. int l=,r;
  12. int *lst[N<<],cnt,tot;
  13. struct node{
  14. int l,r,len;
  15. bool operator<(const node &a)const{return len<a.len;}
  16. }a[N],Q[N];
  17.  
  18. il bool cmp(const int *a,const int *b) {return *a<*b;}
  19.  
  20. il int gi(){
  21. int a=;char x=getchar();bool f=;
  22. while((x<''||x>'')&&x!='-')x=getchar();
  23. if(x=='-')x=getchar(),f=;
  24. while(x>=''&&x<='')a=(a<<)+(a<<)+x-,x=getchar();
  25. return f?-a:a;
  26. }
  27.  
  28. il void pushup(int rt){maxn[rt]=max(maxn[rt<<],maxn[rt<<|]);}
  29.  
  30. il void pushdown(int rt,int len){
  31. if(add[rt]){
  32. add[rt<<]+=add[rt],
  33. add[rt<<|]+=add[rt];
  34. maxn[rt<<]+=add[rt],
  35. maxn[rt<<|]+=add[rt];
  36. add[rt]=;
  37. }
  38. }
  39.  
  40. il void update(int L,int R,int k,int l,int r,int rt){
  41. pushdown(rt,r-l+);
  42. if(L<=l&&R>=r){maxn[rt]+=k;add[rt]=k;return;}
  43. int m=l+r>>;
  44. if(L<=m) update(L,R,k,lson);
  45. if(R>m) update(L,R,k,rson);
  46. pushup(rt);
  47. }
  48.  
  49. int main(){
  50. n=gi(),m=gi();
  51. For(i,,n) a[i].l=gi(),a[i].r=gi(),a[i].len=a[i].r-a[i].l,lst[++cnt]=&a[i].l,lst[++cnt]=&a[i].r;
  52. sort(lst+,lst+cnt+,cmp);
  53. int k=-;
  54. For(i,,cnt) {
  55. if(*lst[i]!=k) k=*lst[i],*lst[i]=++tot;
  56. else *lst[i]=tot;
  57. }
  58. sort(a+,a+n+);
  59. For(i,,n) {
  60. Q[++r].l=a[i].l,Q[r].r=a[i].r,Q[r].len=a[i].len;
  61. update(a[i].l,a[i].r,,,tot,);
  62. if(maxn[]>=m){
  63. while(l<=r&&maxn[]>=m){
  64. update(Q[l].l,Q[l].r,-,,tot,);
  65. l++;
  66. }
  67. if(maxn[]<m) ans=min(a[i].len-Q[l-].len,ans);
  68. }
  69. }
  70. cout<<(ans==0x7fffffff?-:ans);
  71. return ;
  72. }

P1712 [NOI2016]区间的更多相关文章

  1. Luogu P1712 [NOI2016]区间(线段树)

    P1712 [NOI2016]区间 题意 题目描述 在数轴上有 \(N\) 个闭区间 \([l_1,r_1],[l_2,r_2],...,[l_n,r_n]\) .现在要从中选出 \(M\) 个区间, ...

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

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

  3. 洛谷P1712 [NOI2016]区间 尺取法+线段树+离散化

    洛谷P1712 [NOI2016]区间 noi2016第一题(大概是签到题吧,可我还是不会) 链接在这里 题面可以看链接: 先看题意 这么大的l,r,先来个离散化 很容易,我们可以想到一个结论 假设一 ...

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

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

  5. 并不对劲的bzoj4651:loj2086:uoj222:p1712:[NOI2016]区间

    题目大意 有\(n\)(\(n\leq 5*10^5\))个闭区间\([L_1,R_1],[L_2,R_2],...,[L_n,R_n]\)(\(\forall i\in [1,n],0\leq L_ ...

  6. luogu P1712 [NOI2016]区间

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

  7. [洛谷P1712] NOI2016 区间

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

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

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

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

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

随机推荐

  1. python核心编程2 第十三章 练习

    13-3.对类进行定制.写一个类,用来将浮点型值转换为金额. class MoneyFmt(object): def __init__(self, value=0.0, flag='-'): self ...

  2. TCP/IP协议模型详解

    TCP

  3. phpredis命令

    <?php //redis //检查一个扩展是否已经加载.大小写不敏感. if (!function_exists('redis')) { echo '不支持 redis'; return ; ...

  4. mysql 优化like查询

    1. like %keyword    索引失效,使用全表扫描.但可以通过翻转函数+like前模糊查询+建立翻转函数索引=走翻转函数索引,不走全表扫描. 2. like keyword%    索引有 ...

  5. Scala语法(三)

    模式匹配 1)match val a = 1 val b=a match { *// a match { }返回值赋予变量 b case 1 => "red" case 2 ...

  6. python3 练习题100例 (二十三)与7相关的数

    与7相关的数:如果一个正整数,它能被7整除或者它的十进制表示法中某个位数上的数字为7,则称之为与7相关的数.(10分) 题目内容: 现在我们给定一个正整数n(n<1000),求所有小于等于n的与 ...

  7. Redis缓存数据库的安装与配置(3)

    3 Redis主动同步设置方法 Redis主从同步 1.Redis主从同步特点 一个master可以拥有多个slave 多个slave可以连接同一个master,还可以连接到其他slave 主从复制不 ...

  8. Android面试收集录 文件存储

    1.请描述Android SDK支持哪些文件存储技术? 使用SharePreferences保存key-value类型的数据 流文件存储(openFileOutput+openFileInput或Fi ...

  9. 2844: albus就是要第一个出场

    2844: albus就是要第一个出场 链接 分析: 和HDU3949差不多互逆,这里需要加上相同的数. 结论:所有数任意异或,构成的数出现一样的次数,次数为$2^{n-cnt}$,cnt为线性基的大 ...

  10. elasticsearch 拼音+ik分词,spring data elasticsearch 拼音分词

    elasticsearch 自定义分词器 安装拼音分词器.ik分词器 拼音分词器: https://github.com/medcl/elasticsearch-analysis-pinyin/rel ...