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 }
例题:洛谷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 }