zoukankan      html  css  js  c++  java
  • BZOJ 4653: [Noi2016]区间

    4653: [Noi2016]区间

    Time Limit: 60 Sec  Memory Limit: 256 MB
    Submit: 457  Solved: 245
    [Submit][Status][Discuss]

    Description

    在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。
     
    对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。
     
    求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。

    Input

    第一行包含两个正整数 n,m用空格隔开,意义如上文所述。保证 1≤m≤n
     
    接下来 n行,每行表示一个区间,包含用空格隔开的两个整数 li 和 ri 为该区间的左右端点。
    N<=500000,M<=200000,0≤li≤ri≤10^9

    Output

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

    Sample Input

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

    Sample Output

    2

    HINT

     

    Source

     
    [Submit][Status][Discuss]

    这个题吧,就先拿每条线段的长度排序,然后枚举一下最短线段,发现最长线段只会单调变长,所以只需要知道当前维护的区间内是否有个合法的X使得X存在于区间内至少M条线段内。这个就是线段树支持区间加减,全局最值(当然要先对所有坐标离散化处理)。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 
      5 template <class T>
      6 inline T Max(const T &a, const T &b)
      7 {
      8     return a > b ? a : b;
      9 }
     10 
     11 template <class T>
     12 inline T Min(const T &a, const T &b)
     13 {
     14     return a < b ? a : b;
     15 }
     16 
     17 inline int nextChar(void)
     18 {
     19     static const int siz = 1 << 20;
     20     
     21     static char buf[siz];
     22     static char *hd = buf + siz;
     23     static char *tl = buf + siz;
     24     
     25     if (hd == tl)
     26         fread(hd = buf, 1, siz, stdin);
     27     
     28     return int(*hd++);
     29 }
     30 
     31 inline int nextInt(void)
     32 {
     33     int r = 0, c = nextChar();
     34     
     35     for (; c < 48; c = nextChar());
     36     for (; c > 47; c = nextChar())
     37         r = r * 10 + c - '0';
     38     
     39     return r;
     40 }
     41 
     42 const int mxn = 500005;
     43 const int mxm = 200005;
     44 
     45 int n, m;
     46 
     47 struct line
     48 {
     49     int l, r, len;
     50 }L[mxn], *ln[mxn];
     51 
     52 inline bool cmp(line *a, line *b)
     53 {
     54     return a->len < b->len;
     55 }
     56 
     57 int map[mxn << 1], tot;
     58 
     59 inline int find(int k)
     60 {
     61     int lt = 1, rt = tot, mid, ans;
     62     
     63     while (lt <= rt)
     64     {
     65         mid = (lt + rt) >> 1;
     66         
     67         if (map[mid] <= k)
     68             lt = mid + 1, ans = mid;
     69         else
     70             rt = mid - 1;
     71     }
     72     
     73     return ans;
     74 }
     75 
     76 const int siz = 4000005;
     77 
     78 int tag[siz];
     79 int max[siz];
     80 
     81 void add(int t, int l, int r, int x, int y, int v)
     82 {
     83     if (l == x && r == y)
     84     {
     85         tag[t] += v;
     86         max[t] += v;
     87     }
     88     else
     89     {
     90         int mid = (l + r) >> 1;
     91         
     92         if (tag[t])
     93         {
     94             add(t << 1, l, mid, l, mid, tag[t]);
     95             add(t << 1 | 1, mid + 1, r, mid + 1, r, tag[t]);
     96             
     97             tag[t] = 0;
     98         }
     99         
    100         if (y <= mid)
    101             add(t << 1, l, mid, x, y, v);
    102         else if (x > mid)
    103             add(t << 1 | 1, mid + 1, r, x, y, v);
    104         else
    105             add(t << 1, l, mid, x, mid, v),
    106             add(t << 1 | 1, mid + 1, r, mid + 1, y, v);
    107         
    108         max[t] = Max(max[t << 1], max[t << 1 | 1]);
    109     }
    110 }
    111 
    112 signed main(void)
    113 {
    114     n = nextInt();
    115     m = nextInt();
    116     
    117     for (int i = 1; i <= n; ++i)
    118     {
    119         L[i].l = nextInt();
    120         L[i].r = nextInt();
    121         
    122         L[i].len = L[i].r - L[i].l;
    123         
    124         map[++tot] = L[i].l;
    125         map[++tot] = L[i].r;
    126         
    127         ln[i] = L + i;
    128     }
    129     
    130     std::sort(map + 1, map + tot + 1);
    131         
    132     {
    133         int cnt = 1;
    134         
    135         for (int i = 2; i <= tot; ++i)
    136             if (map[i] != map[cnt])
    137                 map[++cnt] = map[i];
    138             
    139         tot = cnt;
    140     }
    141     
    142     for (int i = 1; i <= n; ++i)
    143     {
    144         L[i].l = find(L[i].l);
    145         L[i].r = find(L[i].r);
    146     }
    147     
    148     std::sort(ln + 1, ln + n + 1, cmp);
    149     
    150     int ans = 1E9 + 7;
    151     
    152     {
    153         int cnt = 0;
    154         
    155         for (int i = 1; i <= n; ++i)
    156         {
    157             while (cnt < n && max[1] < m)
    158             {
    159                 line *t = ln[++cnt];
    160                 
    161                 add(1, 1, tot, t->l, t->r, 1);
    162             }
    163             
    164             if (max[1] >= m)
    165                 ans = Min(ans, ln[cnt]->len - ln[i]->len);
    166             
    167             add(1, 1, tot, ln[i]->l, ln[i]->r, -1);
    168         }
    169     }
    170     
    171     if (ans == 1E9 + 7)
    172         puts("-1");
    173     else
    174         printf("%d
    ", ans);
    175 }

    @Author: YouSiki

  • 相关阅读:
    面试热点|理解TCP/IP传输层拥塞控制算法
    mysql中使用存储过程方法中的注意事项
    mysql 游标的使用方法
    php mkdir No such file or director问题
    curl 出现错误的调试方法
    xp与win7双系统时删除win7启动菜单
    退回win7后无法上网 的解决方法
    Windows7安装程序无法定位现有系统分区,也无法创建新的系统分区
    YII 框架在windows系统下的安装
    php 在服务器端开启错误日志记录方法
  • 原文地址:https://www.cnblogs.com/yousiki/p/6431801.html
Copyright © 2011-2022 走看看