UVA12538 自带版本控制功能的IDE Version Controlled IDE

· · 题解

自带版本控制功能的 IDE Version Controlled IDE

题目翻译:

题目比较简单明了,直接在原题看即可。

又是一道可以用 rope 水掉的紫题

所以什么是 rope?

简介:

他是一个 STL 中自带的一种数据结构,是 pb_ds(Policy-Based Data Structures)库 的一个分支,由于他的底层是可持久化平衡树——红黑树,或块状链表。所以他的操作的复杂度几乎约等于 O(\log n)\sqrt n。它可支持操作较多,完全可以理解成加强版的 vector。

最为抽象的是,它可以几乎以 O(1) 的复杂度复制一份,且空间消耗不算太大,这导致他可以代替实现繁琐的可持久化平衡树、可持久化线段树(主席树)、可持久化并查集等等。

其可以以很小的代码量和调试难度骗得较高得分,且 noip 可以使用。

使用方法:

准备:

对与 rope 的使用必须要要调用其库和名名空间名。(因为它不包含在万能头中,且不是 std 命名)

#include<ext/rope>
using namespace __gnu_cxx;

定义:

其定义方式与其他 STL 的定义方式相同,如 rope<int>a。若要定义一个字符 rope 可以rope<char>ccrope c,其类似与一个字符串。

操作:

字符串 rope(crope)

首先,我们定义了一个 crope a;

以上,s 均为字符串(stringchar[])类型,c 为字符(char)类型,npx 均为整型。

数组 rope(rope<int>)

和字符串 rope 的操作差不多,只是把上文中的字符串参数换成了数组。

数组 rope 可以用 a.append(x) 来在末尾插入一个数 x,当然也可以用类似于上文的方法把一个数组连接到末尾,这里不再赘述。

数组 rope 也支持 substr 操作,用于截取其中的一段数。

其他常用操作:

与其他普通的 STL 一样支持:

我们定义两个 rope 一个为 nowpast 分别表示当前正在维护的,和之前的版本。对于每一次操作结束后都可以将 past[++cnt]=now(没错直接等于就 O(1) 复制了)其中 cnt 为版本数。这样需要调用时就直接找到历史版本查询即可。

本题思路:

用一个 past[cnt] 的 rope 来储存历史版本,没修改一次就储存一次,再用 now 来储存当前版本,其余操作没有什么区别。

完整代码

#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
const int N=5e4+10;
char s[N];
int cnt,d;
crope now,past[N];
int main(){
    int n;
    scanf("%d",&n);
    while(n--){
        int op;
        scanf("%d",&op);
        if(op==1){
            int p;
            scanf("%d",&p);
            p-=d;
            scanf("%s",s);
            now.insert(p,s);
            past[++cnt]=now;
        }
        else if(op==2){
            int p,c;
            scanf("%d%d",&p,&c);
            p-=d;
            c-=d;
            now.erase(p-1,c);
            past[++cnt]=now;
        }
        else if(op==3){
            int v,p,c;
            scanf("%d%d%d",&v,&p,&c);
            v-=d;
            p-=d;
            c-=d;
            crope ans=past[v].substr(p-1,c);
            d+=count(ans.begin(),ans.end(),'c');
            cout<<ans<<endl;
        }
    }
}

rope 讲解