二逼平衡树(树套树)

Posted ac-evil

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二逼平衡树(树套树)相关的知识,希望对你有一定的参考价值。

第一次写树套树,在一定帮助下学习,调码3h。

用线段树套平衡树,

对于区间内排名的查询可以解决了;//$O(log^2n)$

对于查询区间排名为k的数,二分答案再判断;//$O(log^3n)$

修改数值直接修改;// $O(log^2n)$

前驱后继,线段树递归区间时,查询每个完全包括的区间数v的前驱后继,最后取min/max即可。// $O(log^2n)$

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 #define re register
  6 #define rep(i, a, b) for (re int i = a; i <= b; ++i)
  7 #define repd(i, a, b) for (re int i = a; i >= b; --i)
  8 #define maxx(a, b) a = max(a, b);
  9 #define minn(a, b) a = min(a, b);
 10 #define LL long long
 11 #define INF (1 << 30)
 12 
 13 inline int read() {
 14     int w = 0, f = 1; char c = getchar();
 15     while (!isdigit(c)) f = c == - ? -1 : f, c = getchar();
 16     while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ 0), c = getchar();
 17     return w * f;
 18 }
 19 
 20 const int maxn = 5e4 + 5;
 21 
 22 struct Node {
 23     Node* ch[2];
 24     int v, s, r;
 25     Node(int v, Node *son) : v(v) { s = 1; r = rand(); ch[0] = ch[1] = son; }
 26     void maintain() { s = ch[0]->s + ch[1]->s + 1; }
 27 } *null;
 28 
 29 void initnull() { null = new Node(0, NULL); null->ch[0] = null->ch[1] = null; null->s = 0; }
 30 
 31 Node* merge(Node *a, Node *b) {
 32     if (a == null) return b;
 33     if (b == null) return a;
 34     if (a->r > b->r) { a->ch[1] = merge(a->ch[1], b); a->maintain(); return a; }
 35     b->ch[0] = merge(a, b->ch[0]); b->maintain(); return b;
 36 }
 37 
 38 void split_val(Node *o, int v, Node* &l, Node* &r) {
 39     if (o == null) { l = r = null; return; }
 40     if (o->v <= v) { l = o; split_val(o->ch[1], v, l->ch[1], r); }
 41     else { r = o; split_val(o->ch[0], v, l, r->ch[0]); }
 42     o->maintain();
 43 }
 44 
 45 void split_rank(Node *o, int k, Node* &l, Node* &r) { // 这个过程好像没用
 46     if (o == null) { l = r = null; return; }
 47     if (o->ch[0]->s + 1 <= k) { l = o; split_rank(o->ch[1], k - o->ch[0]->s - 1, l->ch[1], r); }
 48     else { r = o; split_rank(o->ch[0], k, l, r->ch[0]); }
 49     o->maintain();
 50 }
 51 
 52 void insert(Node* &root, int v) {
 53     Node *l, *r;
 54     split_val(root, v, l, r);
 55     root = merge(merge(l, new Node(v, null)), r);
 56 }
 57 
 58 void remove(Node* &root, int v) {
 59     Node *l, *mid, *r;
 60     split_val(root, v-1, l, r);
 61     split_val(r, v, mid, r);
 62     root = merge(merge(l, merge(mid->ch[0], mid->ch[1])), r);
 63     delete mid;
 64 }
 65 
 66 int get_rank(Node *o, int v) {
 67     if (o == null) return 0;
 68     if (o->v < v) return get_rank(o->ch[1], v) + o->ch[0]->s + 1;
 69     return get_rank(o->ch[0], v);
 70 }
 71 
 72 int get_val(Node *o, int k) {
 73     if (o == null) return -INF;
 74     if (k <= o->ch[0]->s) return get_val(o->ch[0], k);
 75     if (k > o->ch[0]->s + 1) return get_val(o->ch[1], k - o->ch[0]->s - 1);
 76     return o->v;
 77 }
 78 
 79 #define ERROR 2147483647
 80 
 81 int get_pre(Node *o, int v) {
 82     if (o == null) return -ERROR;
 83     if (o->v >= v) return get_pre(o->ch[0], v);
 84     return max(o->v, get_pre(o->ch[1], v));
 85 }
 86 
 87 int get_next(Node *o, int v) {
 88     if (o == null) return ERROR;
 89     if (o->v <= v) return get_next(o->ch[1], v);
 90     return min(o->v, get_next(o->ch[0], v));
 91 }
 92 
 93 int a[maxn], n, m;
 94 
 95 void out(Node *o) {
 96     if (o == null) return;
 97     out(o->ch[0]);
 98     printf("%d ", o->v);
 99     out(o->ch[1]);
100 }
101 
102 struct Seg_tree {
103 #define lson (o << 1)
104 #define rson (o << 1 | 1)
105     Node *root[maxn << 4];
106     void build(int o, int l, int r) {
107         root[o] = null;
108         rep(i, l, r)
109             insert(root[o], a[i]);
110         if (l == r) return;
111         int mid = (l + r) >> 1;
112         build(lson, l, mid), build(rson, mid+1, r);
113         //out(root[o]); puts("
");
114     }
115     void modify(int o, int l, int r, int p, int ov, int nv) {
116         //reset(root[o], p, v);
117         remove(root[o], ov);
118         insert(root[o], nv);
119         if (l == r) return;
120         int mid = (l + r) >> 1;
121         if (p <= mid) modify(lson, l, mid, p, ov, nv);
122         else modify(rson, mid+1, r, p, ov, nv);
123     }
124     int query_rank(int o, int l, int r, int ql, int qr, int v) {
125         if (r < ql || qr < l) return 0;
126         if (ql <= l && r <= qr) return get_rank(root[o], v);
127         int mid = (l + r) >> 1;
128         return query_rank(lson, l, mid, ql, qr, v) + query_rank(rson, mid+1, r, ql, qr, v);
129     }
130     int query_val(int ql, int qr, int k) {
131         int l = 0, r = 1e8;
132         while (l < r) {
133             int mid = (l + r + 1) >> 1, cmp = query_rank(1, 1, n, ql, qr, mid);
134             if (cmp >= k) r = mid-1;
135             else if (cmp < k) l = mid;
136         }
137         return l;
138     }
139     int query_pre(int o, int l, int r, int ql, int qr, int v) {
140         if (r < ql || qr < l) return -ERROR; 
141         if (ql <= l && r <= qr) return get_pre(root[o], v);
142         int mid = (l + r) >> 1;
143         return max(query_pre(lson, l, mid, ql, qr, v), query_pre(rson, mid+1, r, ql, qr, v));
144     }
145     int query_next(int o, int l, int r, int ql, int qr, int v) {
146         if (r < ql || qr < l) return ERROR;
147         if (ql <= l && r <= qr) return get_next(root[o], v);
148         int mid = (l + r) >> 1;
149         return min(query_next(lson, l, mid, ql, qr, v), query_next(rson, mid+1, r, ql, qr, v));
150     }
151 } seg_root;
152 
153 #undef ERROR
154 
155 int main() {
156     srand(19260817);
157     initnull();
158     n = read(), m = read();
159     rep(i, 1, n) a[i] = read();
160     seg_root.build(1, 1, n);
161     while (m--) {
162         int opt = read();
163         if (opt == 3) {
164             int pos = read(), k = read();
165             seg_root.modify(1, 1, n, pos, a[pos], k);
166             a[pos] = k;
167         }
168         else {
169             int l = read(), r = read(), k = read();
170             if (opt == 1) printf("%d
", seg_root.query_rank(1, 1, n, l, r, k)+1);
171             if (opt == 2) printf("%d
", seg_root.query_val(l, r, k));
172             if (opt == 4) printf("%d
", seg_root.query_pre(1, 1, n, l, r, k));
173             if (opt == 5) printf("%d
", seg_root.query_next(1, 1, n, l, r, k));
174         }
175     }
176     return 0;
177 }

 

以上是关于二逼平衡树(树套树)的主要内容,如果未能解决你的问题,请参考以下文章

模板二逼平衡树(树套树)

二逼平衡树(树套树)

洛谷 P3380 模板二逼平衡树(树套树)

bzoj3196: Tyvj 1730 二逼平衡树 树套树

BZOJ3196二逼平衡树树套树

P3380 模板二逼平衡树(树套树)