zoukankan      html  css  js  c++  java
  • DynamicSegmentTree

    最近尝试了一下动态开点线段树,英文直译就是Dynamic Open Point Segment Tree,太SB了。

    就跟之前的主席树写法差不多。

    1 if(!x || x == y) {
    2     x = ++tot;
    3 }
    主席树
    1 if(!o) {
    2     o = ++tot;
    3 }
    动态开点线段树

    实际上当普通线段树用就行了......

    例题:洛谷P1908 逆序对

    我们可以不离散化,使用动态开点,直接在1e9上开值域线段树。吸氧后堪堪A掉。

     1 // luogu-judger-enable-o2
     2 #include <cstdio>
     3 
     4 typedef long long LL;
     5 const int N = 500010;
     6 
     7 int sum[N * 20], tot, ls[N * 20], rs[N * 20], a[N], root;
     8 
     9 void add(int L, int R, int l, int r, int &o) {
    10     if(!o) {
    11         o = ++tot;
    12     }
    13     if(L <= l && r <= R) {
    14         sum[o]++;
    15         return;
    16     }
    17     int mid = (l + r) >> 1;
    18     if(L <= mid) {
    19         add(L, R, l, mid, ls[o]);
    20     }
    21     if(mid < R) {
    22         add(L, R, mid + 1, r, rs[o]);
    23     }
    24     sum[o] = sum[ls[o]] + sum[rs[o]];
    25     return;
    26 }
    27 
    28 int ask(int L, int R, int l, int r, int o) {
    29     if(!o) {
    30         return 0;
    31     }
    32     if(L <= l && r <= R) {
    33         return sum[o];
    34     }
    35     int mid = (l + r) >> 1;
    36     int ans = 0;
    37     if(L <= mid) {
    38         ans += ask(L, R, l, mid, ls[o]);
    39     }
    40     if(mid < R) {
    41         ans += ask(L, R, mid + 1, r, rs[o]);
    42     }
    43     return ans;
    44 }
    45 
    46 int main() {
    47     //printf("%d", sizeof(sum) / 1024 / 1024 * 3);
    48     int n, m = 1e9;
    49     
    50     scanf("%d", &n);
    51     for(int i = 1; i <= n; i++) {
    52         scanf("%d", &a[i]);
    53     }
    54     
    55     LL ans = 0;
    56     for(int i = 1; i <= n; i++) {
    57         ans += ask(a[i] + 1, m, 1, m, 1);
    58         add(a[i], a[i], 1, m, root);
    59     }
    60     printf("%lld", ans);
    61     return 0;
    62 }
    AC代码

    例题:洛谷P2471 降雨量

    这个题的难点TM在于分类讨论......大毒瘤。

    对于未知的位置,我们用一个bool数组维护就行了。

    询问的时候查x,y,(x,y)三段,然后暴力讨论.....

      1 #include <cstdio>
      2 #include <algorithm>
      3 
      4 const int N = 50010, E = 1e9 + 1;
      5 
      6 int root, large[N * 50], tot, ls[N * 50], rs[N * 50];
      7 bool maybe, sure[N * 50];
      8 
      9 void change(int p, int v, int l, int r, int &o) {
     10     //printf("change : %d %d %d %d 
    ", p, v, l, r);
     11     //getchar();
     12     if(!o) {
     13         o = ++tot;
     14     }
     15     if(l == r) {
     16         large[o] = v;
     17         sure[o] = 1;
     18         return;
     19     }
     20     int mid = l + (r - l) / 2;
     21     if(p <= mid) {
     22         change(p, v, l, mid, ls[o]);
     23     }
     24     else {
     25         change(p, v, mid + 1, r, rs[o]);
     26     }
     27     large[o] = std::max(large[ls[o]], large[rs[o]]);
     28     sure[o] = sure[ls[o]] & sure[rs[o]];
     29     return;
     30 }
     31 
     32 int ask(int L, int R, int l, int r, int o) {
     33     //printf("%d %d %d %d 
    ", L, R, l, r);
     34     if(!o) {
     35         maybe = 1;
     36         return 0;
     37     }
     38     if(L <= l && r <= R) {
     39         if(!sure[o]) {
     40             maybe = 1;
     41         }
     42         return large[o];
     43     }
     44     int mid = l + (r - l) / 2;
     45     int ans = 0;
     46     if(L <= mid) {
     47         ans = std::max(ans, ask(L, R, l, mid, ls[o]));
     48     }
     49     if(mid < R) {
     50         ans = std::max(ans, ask(L, R, mid + 1, r, rs[o]));
     51     }
     52     return ans;
     53 }
     54 
     55 int main() {
     56     int n, limit = E << 1, x, y;
     57     scanf("%d", &n);
     58     for(int i = 1; i <= n; i++) {
     59         scanf("%d%d", &x, &y);
     60         change(x + E, y, 1, limit, root);
     61     }
     62     scanf("%d", &n);
     63     while(n--) {
     64         scanf("%d%d", &y, &x);
     65         if(y == x) {
     66             printf("true
    ");
     67             continue;
     68         }
     69         int c = ask(y + E, y + E, 1, limit, root);
     70         int cc = maybe;
     71         maybe = 0;
     72         int d = ask(x + E, x + E, 1, limit, root);
     73         int dd = maybe;
     74         maybe = 0;
     75         //printf("%d %d %d %d 
    ", c, cc, d, dd);    false -> maybe 
     76         if(y + 1 == x) {
     77             if(cc || dd){
     78                 printf("maybe
    ");
     79             }
     80             else {
     81                 if(c >= d) {
     82                     printf("true
    ");
     83                 }
     84                 else {
     85                     printf("false
    ");
     86                 }
     87             }
     88             continue;
     89         }
     90         int e = ask(y + 1 + E, x - 1 + E, 1, limit, root);
     91         int ee = maybe;
     92         maybe = 0;
     93         //printf("%d %d 
    ", e, ee);
     94         if(dd) {
     95             if(cc) {
     96                 printf("maybe
    ");
     97             }
     98             else {
     99                 if(e >= c) {
    100                     printf("false
    ");
    101                 }
    102                 else {
    103                     printf("maybe
    ");
    104                 }
    105             }
    106             continue;
    107         }
    108         if(cc) {
    109             if(e >= d) {
    110                 printf("false
    ");
    111             }
    112             else {
    113                 printf("maybe
    ");
    114             }
    115             continue;
    116         }
    117         if(ee) {
    118             if(e >= d || c < d) {
    119                 printf("false
    ");
    120             }
    121             else {
    122                 printf("maybe
    ");
    123             }
    124             continue;
    125         }
    126         if(e >= d || c < d) {
    127             printf("false
    ");
    128         }
    129         else {
    130             printf("true
    ");
    131         }
    132     }
    133     
    134     return 0;
    135 }
    AC代码
  • 相关阅读:
    论文连接
    MySQL中的datetime与timestamp比较
    查看挂载情况
    insertable = false, updatable = false的使用
    umount: /home: device is busy
    LVM
    erase-credentials配置
    <T> List<T>前面<T>的意思
    Java 内部类 this
    AuthenticationManager, ProviderManager 和 AuthenticationProvider
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/9823168.html
Copyright © 2011-2022 走看看