zoukankan      html  css  js  c++  java
  • 洛谷P1712 区间

    题意:给你n个区间,从中选择m个,使得它们有交,且最长与最短区间的差值最小。

    解:这道题我想了好多的,nlog²n错的,nlogn错的,最后终于想出nlogn的了......

    把区间按照长度排序,然后依次在线段树上加。

    如果某一次等于m了,那么一个一个删,删到小于m的时候,更新答案。

    证明:那些之前的区间如果想要成为答案,那么必须是和比当前这个还靠前的区间来组成。

    这样的话当到这一个时,之前的要么被计算,要么不会更优。故可以删掉。

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 const int N = 500010, INF = 0x3f3f3f3f;
     5 
     6 int sum[N << 3], large[N << 3], tag[N << 3], X[N << 1];
     7 
     8 struct ITV {
     9     int r, l, len;
    10     inline bool operator <(const ITV &w) const {
    11        return len < w.len;
    12     }
    13 }a[N];
    14 
    15 inline void pushup(int o) {
    16     int ls = o << 1;
    17     int rs = ls | 1;
    18     sum[o] = sum[ls] + sum[rs];
    19     large[o] = std::max(large[ls], large[rs]);
    20     return;
    21 }
    22 
    23 inline void pushdown(int l, int r, int o) {
    24     if(tag[o]) {
    25         int ls = o << 1;
    26         int rs = ls | 1;
    27         int mid = (l + r) >> 1;
    28         tag[ls] += tag[o];
    29         tag[rs] += tag[o];
    30         sum[ls] += (mid - l + 1) * tag[o];
    31         sum[rs] += (r - mid) * tag[o];
    32         large[ls] += tag[o];
    33         large[rs] += tag[o];
    34         tag[o] = 0;
    35     }
    36     return;
    37 }
    38 
    39 inline void add(int L, int R, int v, int l, int r, int o) {
    40     if(L <= l && r <= R) {
    41         tag[o] += v;
    42         sum[o] += v * (r - l + 1);
    43         large[o] += v;
    44         return;
    45     }
    46     pushdown(l, r, o);
    47     int mid = (l + r) >> 1;
    48     if(L <= mid) {
    49         add(L, R, v, l, mid, o << 1);
    50     }
    51     if(mid < R) {
    52         add(L, R, v, mid + 1, r, o << 1 | 1);
    53     }
    54     pushup(o);
    55     return;
    56 }
    57 
    58 int main() {
    59 
    60     int n, m;
    61     scanf("%d%d", &n, &m);
    62     for(int i = 1; i <= n; i++) {
    63         scanf("%d%d", &a[i].l, &a[i].r);
    64         a[i].len = a[i].r - a[i].l;
    65         X[i << 1] = a[i].l;
    66         X[(i << 1) - 1] = a[i].r;
    67     }
    68     std::sort(a + 1, a + n + 1);
    69     std::sort(X + 1, X + (n << 1) + 1);
    70     int t = std::unique(X + 1, X + (n << 1) + 1) - X - 1;
    71     int j = 1, ans = INF;
    72     for(int i = 1; i <= n; i++) {
    73         a[i].l = std::lower_bound(X + 1, X + t + 1, a[i].l) - X;
    74         a[i].r = std::lower_bound(X + 1, X + t + 1, a[i].r) - X;
    75         add(a[i].l, a[i].r, 1, 1, t, 1);
    76         while(large[1] >= m) {
    77             add(a[j].l, a[j].r, -1, 1, t, 1);
    78             //printf("large[1] = %d  ans = %d 
     i = %d j = %d 
    ", large[1], ans, i, j);
    79             ans = std::min(ans, a[i].len - a[j].len);
    80             j++;
    81         }
    82     }
    83     if(ans == INF) {
    84         ans = -1;
    85     }
    86     printf("%d
    ", ans);
    87     return 0;
    88 }
    AC代码

    这个sum其实是不必要的。

    然后我还用动态开点写了一发......被卡空间了。

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 const int N = 500010, INF = 0x3f3f3f3f;
     5 
     6 int large[N * 31], tag[N * 31], root, ls[N * 31], rs[N * 31], tot;
     7 
     8 struct ITV {
     9     int r, l, len;
    10     inline bool operator <(const ITV &w) const {
    11        return len < w.len;
    12     }
    13 }a[N];
    14 
    15 inline void pushup(int o) {
    16     large[o] = std::max(large[ls[o]], large[rs[o]]);
    17     return;
    18 }
    19 
    20 inline void pushdown(int l, int r, int o) {
    21     if(tag[o]) {
    22         int mid = (l + r) >> 1;
    23         if(ls[o]) {
    24             large[ls[o]] += tag[o];
    25             tag[ls[o]] += tag[o];
    26         }
    27         if(rs[o]) {
    28             large[rs[o]] += tag[o];
    29             tag[rs[o]] += tag[o];
    30         }
    31         tag[o] = 0;
    32     }
    33     return;
    34 }
    35 
    36 inline void add(int L, int R, int v, int l, int r, int &o) {
    37     if(!o) {
    38         o = ++tot;
    39     }
    40     if(L <= l && r <= R) {
    41         tag[o] += v;
    42         large[o] += v;
    43         return;
    44     }
    45     if(!ls[o]) {
    46         ls[o] = ++tot;
    47     }
    48     if(!rs[o]) {
    49         rs[o] = ++tot;
    50     }
    51     pushdown(l, r, o);
    52     int mid = (l + r) >> 1;
    53     if(L <= mid) {
    54         add(L, R, v, l, mid, ls[o]);
    55     }
    56     if(mid < R) {
    57         add(L, R, v, mid + 1, r, rs[o]);
    58     }
    59     pushup(o);
    60     return;
    61 }
    62 
    63 int main() {
    64 
    65     int n, m, lm = 0;
    66     scanf("%d%d", &n, &m);
    67     for(int i = 1; i <= n; i++) {
    68         scanf("%d%d", &a[i].l, &a[i].r);
    69         a[i].len = a[i].r - a[i].l;
    70         lm = std::max(lm, a[i].r);
    71     }
    72     std::sort(a + 1, a + n + 1);
    73     int j = 1, ans = INF;
    74     for(int i = 1; i <= n; i++) {
    75         add(a[i].l, a[i].r, 1, 1, lm, root);
    76         while(large[1] >= m) {
    77             add(a[j].l, a[j].r, -1, 1, lm, root);
    78             //printf("large[1] = %d  ans = %d 
     i = %d j = %d 
    ", large[1], ans, i, j);
    79             ans = std::min(ans, a[i].len - a[j].len);
    80             j++;
    81         }
    82     }
    83     if(ans == INF) {
    84         ans = -1;
    85     }
    86     printf("%d
    ", ans);
    87     return 0;
    88 }
    95分动态开点
  • 相关阅读:
    安卓 广播机制
    安卓 活动的启动模式
    安卓 生命周期
    安卓六大布局
    day4-list,列表
    Leetcode 947 移除最多的同行或同列石头
    Leetcode 628三个数的最大乘积
    Leetcode 1584连接所有点的最小费用
    Leetcode 721 账户合并
    Leetcode 103 二叉树的锯齿层序遍历
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10044358.html
Copyright © 2011-2022 走看看