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 都要先減去dd 是之前所有的第三種操作中字符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;
}
發佈了601 篇原創文章 · 獲贊 25 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章