uva12538
可持久化treap
抄了个模板。
可持久化treap和主席树一样,都是利用了以前的节点来节省空间。但是却又有些不一样。可持久化treap基于两种操作:merge和split。其他操作都是由这两种操作完成,除了build。这两种操作都要满足第一颗treap的所有节点都是小于第二颗treap,这样才能log合并。
对于可持久化treap,可以这样理解:每次split,就是找出一颗treap中小于或大于的节点,然后向主席树一样新建一些节点分别连接起来,merge也是用一些新的节点将两颗treap连接起来,这样就起到了可持久化化treap的效果,原来的treap没有改变,只是新加入了一些节点将他们连接起来,又构成了一颗新的treap。
所以这样空间消耗还是很大的。无论什么操作都要新建节点。
#include<bits/stdc++.h> using namespace std; typedef pair<int, int> PII; const int N = 5000010; int n, delta, cnt, now; int size[N], rnd[N], child[N][2], root[N]; char c[N], s[N]; void update(int x) { size[x] = size[child[x][0]] + size[child[x][1]] + 1; } int newnode(char v) { ++cnt; size[cnt] = 1; rnd[cnt] = rand(); c[cnt] = v; return cnt; } int copy(int a) { ++cnt; child[cnt][0] = child[a][0]; child[cnt][1] = child[a][1]; size[cnt] = size[a]; rnd[cnt] = rnd[a]; c[cnt] = c[a]; return cnt; } int merge(int x, int y) { if(!x) return y; if(!y) return x; int z; if(rnd[x] < rnd[y]) { z = copy(x); child[z][1] = merge(child[z][1], y); } else { z = copy(y); child[z][0] = merge(x, child[z][0]); } update(z); return z; } PII split(int x, int k) { if(!x) return make_pair(0, 0); if(k <= size[child[x][0]]) { int z = copy(x); PII ret = split(child[x][0], k); child[z][0] = ret.second; ret.second = z; update(z); return ret; } else { int z = copy(x); PII ret = split(child[x][1], k - size[child[x][0]] - 1); child[z][1] = ret.first; ret.first = z; update(z); return ret; } } void build(int &x, int l, int r) { if(l > r) return; int mid = (l + r) >> 1; x = newnode(s[mid]); build(child[x][0], l, mid - 1); build(child[x][1], mid + 1, r); update(x); } void ins(int &x, int last, int pos) { int a, b, c, len = strlen(s + 1); PII t = split(last, pos); build(c, 1, len); x = merge(merge(t.first, c), t.second); } void del(int &x, int last, int pos, int len) { int a, b, c; PII t1 = split(last, pos - 1); PII t2 = split(t1.second, len); x = merge(t1.first, t2.second); } void print(int x) { if(!x) return; print(child[x][0]); printf("%c", c[x]); if(c[x] == 'c') ++delta; print(child[x][1]); } void print(int x, int pos, int len) { PII t1 = split(x, pos - 1); PII t2 = split(t1.second, len); print(t2.first); puts(""); } int main() { srand(19992147); scanf("%d", &n); while(n--) { int opt, pos, len, x; scanf("%d", &opt); if(opt == 1) { scanf("%d%s", &pos, s + 1); pos -= delta; ins(root[now + 1], root[now], pos); ++now; } if(opt == 2) { scanf("%d%d", &pos, &len); pos -= delta; len -= delta; del(root[now + 1], root[now], pos, len); ++now; } if(opt == 3) { scanf("%d%d%d", &x, &pos, &len); x -= delta; pos -= delta; len -=delta; print(root[x], pos, len); } // printf("root[%d]=%d\n", now, root[now]); } return 0; }