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 \n", 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 \n", 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\n");
 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 \n", c, cc, d, dd);    false -> maybe 
 76         if(y + 1 == x) {
 77             if(cc || dd){
 78                 printf("maybe\n");
 79             }
 80             else {
 81                 if(c >= d) {
 82                     printf("true\n");
 83                 }
 84                 else {
 85                     printf("false\n");
 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 \n", e, ee);
 94         if(dd) {
 95             if(cc) {
 96                 printf("maybe\n");
 97             }
 98             else {
 99                 if(e >= c) {
100                     printf("false\n");
101                 }
102                 else {
103                     printf("maybe\n");
104                 }
105             }
106             continue;
107         }
108         if(cc) {
109             if(e >= d) {
110                 printf("false\n");
111             }
112             else {
113                 printf("maybe\n");
114             }
115             continue;
116         }
117         if(ee) {
118             if(e >= d || c < d) {
119                 printf("false\n");
120             }
121             else {
122                 printf("maybe\n");
123             }
124             continue;
125         }
126         if(e >= d || c < d) {
127             printf("false\n");
128         }
129         else {
130             printf("true\n");
131         }
132     }
133     
134     return 0;
135 }
AC代码

 

posted @ 2018-10-20 21:56  huyufeifei  阅读(275)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜