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;
}
View Code

 

posted @ 2017-06-25 22:29  19992147  阅读(263)  评论(0编辑  收藏  举报