UVA 12538 Version Controlled IDE 可持久化平衡树 || rope

题目:

https://vjudge.net/problem/UVA-12538

题意:

模拟一个版本控制编辑器,有以下操作:

  • 1 p s : 在 p 后面位置插入一个字符串s
  • 2 p c :从第 p 个字符开始删掉c个字符
  • 3 v p c :在第 v 个版本中,从第p个位置开始取 c 个字符并输出
    前两种操作中每个操作后形成一个新版本。为防止预处理,要求输入中的v p c都要先减去 d d是之前所有的第三种操作中字符 c 的个数

思路:

在线询问某个版本的具体情况, 显然是要可持久化的,可以用非旋转treap实现,这里先用rope实现。。。过两天填可持久化平衡树的坑。。。

#include <bits/stdc++.h>
#include <ext/rope>

using namespace std;
using namespace __gnu_cxx;

const int N = 50000 + 10;

char str[N];
crope rs, his[N];

int main()
{
    int n, opt, v, p, len;
    int num = 0, cur = 0;
    scanf("%d", &n);
    while(n--)
    {
        scanf("%d", &opt);
        if(opt == 1)
        {
            scanf("%d%s", &p, str);
            p -= num;
            rs.insert(p, str);
            his[++cur] = rs;
        }
        else if(opt == 2)
        {
            scanf("%d%d", &p, &len);
            p -= num, len -= num;
            rs.erase(p-1, len);
            his[++cur] = rs;
        }
        else if(opt == 3)
        {
            scanf("%d%d%d", &v, &p, &len);
            v -= num, p -= num, len -= num;
            string s = his[v].substr(p-1, len).c_str();
            num += count(s.begin(), s.end(), 'c');
            printf("%s\n", s.c_str());
//            crope tp = his[v].substr(p-1, len);
//            num += count(tp.begin(), tp.end(), 'c');
//            cout << tp << endl;
//            printf("%s\n", tp.c_str());
        }
    }
    return 0;
}
//2017.9.27
//可持久化treap类似于可持久化线段树,原本的形态保持不变,通过新增节点的方式进行merge和split操作,很机智。。。
#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> proot;
const int N = 4000000 + 10, M = 50000 + 10, INF = 0x3f3f3f3f;

struct node
{
    int l, r, val, pri, sz;
    void init(int _val, int _pri, int _sz)
    {
        val = _val, pri = _pri, sz = _sz;
        l = r = 0;
    }
}tr[N];
char s[M];
int root[M];
int tot, num;
void init()
{
    tot = 0;
    tr[0].init(0, 0, 0);
}
int new_node(int val)
{
    tr[++tot].init(val, rand(), 1);
    return tot;
}
void update(int x)
{
    tr[x].sz = 1 + tr[tr[x].l].sz + tr[tr[x].r].sz;
}
int Copy(int x)
{
    tr[++tot] = tr[x];
    return tot;
}
int Merge(int x, int y)
{
    if(!x || !y) return x + y;
    int z;
    if(tr[x].pri < tr[y].pri)
    {
        z = Copy(x);
        tr[z].r = Merge(tr[z].r, y);
    }
    else
    {
        z = Copy(y);
        tr[z].l = Merge(x, tr[z].l);
    }
    update(z);
    return z;
}
proot split(int x, int k)
{
    //if(!k) return proot(0, x);
    if(!x) return proot(0, 0);
    proot y;
    if(k <= tr[tr[x].l].sz)
    {
        int z = Copy(x);
        y = split(tr[x].l, k);
        tr[z].l = y.second;
        y.second = z;
        update(z);
    }
    else
    {
        int z = Copy(x);
        y = split(tr[x].r, k - tr[tr[x].l].sz - 1);
        tr[z].r = y.first;
        y.first = z;
        update(z);
    }
    return y;
}
void build(int &x, int l, int r)
{
    if(l > r) return;
    int mid = (l + r) >> 1;
    x = new_node(s[mid]);
    build(tr[x].l, l, mid-1);
    build(tr[x].r, mid+1, r);
    update(x);
}
void Insert(int &x, int last, int pos)
{
    int len = strlen(s + 1);
    proot y = split(last, pos);
    build(x, 1, len);
    x = Merge(Merge(y.first, x), y.second);
}
void del(int &x, int last, int pos, int len)
{
    proot t1 = split(last, pos-1);
    proot t2 = split(t1.second, len);
    x = Merge(t1.first, t2.second);
}
void print(int x)
{
    if(!x) return;
    print(tr[x].l);
    printf("%c", (char)tr[x].val);
    if(tr[x].val == 'c') ++num;
    print(tr[x].r);
}
void print(int x, int pos, int len)
{
    proot t1 = split(x, pos-1);
    proot t2 = split(t1.second, len);
    print(t2.first);
    printf("\n");
}
int main()
{
    srand((unsigned)time(NULL));
    int n, opt, v, p, len, cur = 0;
    init();
    num = 0;
    scanf("%d", &n);
    while(n--)
    {
        scanf("%d", &opt);
        if(opt == 1)
        {
            scanf("%d%s", &p, s+1);
            p -= num;
            Insert(root[cur+1], root[cur], p);
            ++cur;
        }
        else if(opt == 2)
        {
            scanf("%d%d", &p, &len);
            p -= num, len -= num;
            del(root[cur+1], root[cur], p, len);
            ++cur;
        }
        else if(opt == 3)
        {
            scanf("%d%d%d", &v, &p, &len);
            v -= num, p -= num, len -= num;
            print(root[v], p, len);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值