zoukankan      html  css  js  c++  java
  • [NOI 2016]区间

    Description

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

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

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

    Input

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

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

    Output

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

    Sample Input

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

    Sample Output

    2

    Sample Explanation

    样例图

    如图,当 $n=6,~m=3$ 时,花费最小的方案是选取 $[3,5]$、$[3,4]$、$[1,4]$ 这三个区间,他们共同包含了 $4$ 这个位置,所以是合法的。其中最长的区间是 $[1,4]$,最短的区间是 $[3,4]$,所以它的花费是 $(4−1)−(4−3)=2$。

    Hint

    所有测试数据的范围和特点如下表所示:

    测试点编号$n$$m$$l_i,r_i$
    1 $20$ $9$ $0 le l_i le r_i le 100$
    2 $10$
    3 $199$ $3$ $0 le l_i le r_i le 100000$
    4 $200$
    5 $1000$ $2$
    6 $2000$
    7 $199$ $60$ $0 le l_i le r_i le 5000$
    8 $200$ $50$
    9 $0 le l_i le r_i le 10^9$
    10 $1999$ $500$ $0 le l_i le r_i le 5000$
    11 $2000$ $400$
    12 $500$ $0 le l_i le r_i le 10^9$
    13 $30000$ $2000$ $0 le l_i le r_i le 100000$
    14 $40000$ $1000$
    15 $50000$ $15000$
    16 $100000$ $20000$
    17 $200000$ $0 le l_i le r_i le 10^9$
    18 $300000$ $50000$
    19 $400000$ $90000$
    20 $500000$ $200000$

    时间限制:$3 exttt{s}$

    空间限制:$256 exttt{MB}$

    题解(转载)

    ->原文地址<-

    首先发现那一个相交的点一定可以是区间的某个端点,所以可以离散左右端点,那么问题就简单了,然后仔细推敲,发现可以按区间长度排序,然后不就是尺取法了么?如果有一个点被覆盖的次数$>=m$我们就移动右指针,不然我们就一直往后走,对于覆盖次数$>=m$我们就维护线段树区间最大值,然后区间修改维护指针移动即可。

     1 //It is made by Awson on 2017.10.17
     2 #include <set>
     3 #include <map>
     4 #include <cmath>
     5 #include <ctime>
     6 #include <cmath>
     7 #include <stack>
     8 #include <queue>
     9 #include <vector>
    10 #include <string>
    11 #include <cstdio>
    12 #include <cstdlib>
    13 #include <cstring>
    14 #include <iostream>
    15 #include <algorithm>
    16 #define LL long long
    17 #define Min(a, b) ((a) < (b) ? (a) : (b))
    18 #define Max(a, b) ((a) > (b) ? (a) : (b))
    19 #define sqr(x) ((x)*(x))
    20 #define Lr(x) (x<<1)
    21 #define Rr(x) (x<<1|1)
    22 using namespace std;
    23 const int N = 500000;
    24 
    25 int n, m, ans = 2e9;
    26 struct tt {
    27   int l, r, val;
    28   bool operator < (const tt &b) const{
    29     return val < b.val;
    30   }
    31 }a[N+5];
    32 struct ss {
    33   int val, id, op;
    34   bool operator < (const ss &b) const{
    35     return val < b.val;
    36   }
    37 }b[(N<<1)+5];
    38 struct segment {
    39   int sgm[(N<<3)+5], lazy[(N<<3)+5];
    40   void pushdown(int o) {
    41     sgm[Lr(o)] += lazy[o], sgm[Rr(o)] += lazy[o];
    42     lazy[Lr(o)] += lazy[o], lazy[Rr(o)] += lazy[o];
    43     lazy[o] = 0;
    44   }
    45   void update(int o, int l, int r, int a, int b, int key) {
    46     if (a <= l && r <= b) {
    47       sgm[o] += key, lazy[o] += key;
    48       return;
    49     }
    50     pushdown(o);
    51     int mid = (l+r)>>1;
    52     if (a <= mid) update(Lr(o), l, mid, a, b, key);
    53     if (b > mid) update(Rr(o), mid+1, r, a, b, key);
    54     sgm[o] = Max(sgm[Lr(o)], sgm[Rr(o)]);
    55   }
    56 }T;
    57 
    58 void work() {
    59   scanf("%d%d", &n, &m);
    60   for (int i = 1; i <= n; i++) scanf("%d%d", &a[i].l, &a[i].r), a[i].val = a[i].r-a[i].l;
    61   sort(a+1, a+n+1);
    62   for (int i = 1; i <= n; i++) {
    63     b[(i<<1)-1].val = a[i].l, b[(i<<1)-1].id = i; b[i<<1].val = a[i].r, b[i<<1].id = i;
    64   }
    65   sort(b+1, b+2*n+1); b[0].val = -1;
    66   for (int i = 1; i <= (n<<1); i++) b[i].op = b[i-1].op+(b[i].val != b[i-1].val);
    67   for (int i = 1; i <= (n<<1); i++) { 
    68     if (b[i].val == a[b[i].id].l) a[b[i].id].l = b[i].op;
    69     if (b[i].val == a[b[i].id].r) a[b[i].id].r = b[i].op;
    70   }
    71   int tol = b[n<<1].op, r = 0;
    72   for (int i = 1; i <= n; i++) {
    73     while (r < n && T.sgm[1] < m) {
    74       r++; T.update(1, 1, tol, a[r].l, a[r].r, 1);
    75     }
    76     if (T.sgm[1] >= m) ans = Min(ans, a[r].val-a[i].val);
    77     else break;
    78     T.update(1, 1, tol, a[i].l, a[i].r, -1);
    79   }
    80   printf("%d
    ", ans == 2e9 ? -1 : ans);
    81 }
    82 int main() {
    83   work();
    84   return 0;
    85 }
  • 相关阅读:
    Kubernetes进阶实战读书笔记:持久化存储卷(pvc详解)
    Nginx核心知识100讲学习笔记(陶辉)详解HTTP模块(接受请求模块|正则表达式|冲突合并)
    Nginx核心知识100讲学习笔记(陶辉)详解HTTP模块(详解11阶段)
    WIndows 编辑的文件的文件在Linux下查看每行末尾有 ^M
    JQuery ajax 使用
    查看oracle死锁进程并结束死锁
    Oracle 死锁处理(查看锁表语句及解锁)
    BS表单编程注意事项
    Delphi MDI多文档架构几个问题解决
    Delphi MDI子窗体
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7683410.html
Copyright © 2011-2022 走看看