stl学习(三)crope的用法

转载自http://blog.csdn.net/iamzky/article/details/38348653

曾经我不会写平衡树……于是在STL中乱翻……学到了pb_ds库中的SXBK的斐波那契堆、支持kth的set,和……ext/rope

先发一个官方的 说明 (鸣谢maoxiaohan1999):

http://www.sgi.com/tech/stl/Rope.html

再来例题

IOI2012

scrivener

题意

设计支持如下 3 种操作: 
1.T x:在文章末尾打下一个小写字母 x。(type 操作) 
2.U x:撤销最后的x 次修改操作。(Undo 操作) 
(注意Query 操作并不算修改操作) 
3.Q x:询问当前文章中第x 个字母并输出。(Query 操作)

操作数n<=100000 在线算法

clj都说这是道rope傻逼题……

我的rope标程:

    #include  
    #include  
    #include  
    #include  
    #include  
    #include  
    using namespace std;  
    using namespace __gnu_cxx;  
    const int maxn=1e5+10;  
    rope *his[maxn];  
    int n;  
    int d[maxn];  
    inline int lowbit(int x){  
        return x&-x;  
    }  
    inline void updata(int x){  
        while(x<=n){  
            d[x]++;  
            x+=lowbit(x);  
        }  
    }  
    inline int get(int x){  
        int res=0;  
        while(x){  
            res+=d[x];  
            x-=lowbit(x);  
        }return res;  
    }  
    inline char getC(){  
        char ch=getchar();  
        while(!isalpha(ch))ch=getchar();  
        return ch;  
    }  
    inline int getint(){  
        int res=0;  
        char ch,ok=0;  
        while(ch=getchar()){  
            if(isdigit(ch)){  
                res*=10;res+=ch-'0';ok=1;  
            }else if(ok)break;  
        }return res;  
    }  
    void deb(rope s){  
        for(int i=0;i();  
        for(int i=1;i<=n;i++){  
            his[i]=new rope(*his[i-1]);  
    //      deb(*his[i]);  
            char opt=getC();  
            if(opt=='T'){  
                char x=getC();  
                his[i]->push_back(x);  
                updata(i);  
            }else  
            if(opt=='U'){  
                updata(i);  
                int x=getint();  
                int l=1,r=i,mid,now=get(i);  
                while(l>1;  
                    if(now-get(mid)>x)  
                        l=mid+1;  
                    else  
                        r=mid;  
                }  
                his[i]=his[l-1];  
                  
            }else  
            if(opt=='Q'){  
                int x=getint()-1;  
                putchar(his[i]->at(x));  
                putchar('\n');    
            }  
    //      deb(*his[i]);  
        }  
        return 0;  
    }  

可持久化在哪里呢?

    his[i]=new rope(*his[i-1]);  

就是这一句!它可以实现O(1)的拷贝历史版本,由于rope的底层是平衡树,copy时copy根节点就行了

用它就可以轻松实现可持久化数组

其余操作不用多说

例二

AHOI2006文本编辑器editor

题意

设计数据结构支持

插入删除反转字符串

    #include   
    #include   
    #include   
    #include   
    using namespace std;  
    using namespace __gnu_cxx;  
    crope a,b,tmp;  
    char s[10];  
    int now,n,len,size;  
    char str[2000000],rstr[2000000];  
    int main(){  
        scanf("%d",&n);  
        while(n--){  
            scanf("%s",s);  
            switch(s[0]){  
                case 'M':{scanf("%d",&now);break;}  
                case 'P':{now--;break;}  
                case 'N':{now++;break;}  
                case 'G':{putchar(a[now]);putchar('\n');break;}  
                case 'I':{  
                    scanf("%d",&size);  
                    len=a.length();  
                    for(int i=0;i
由于rope的底层实现,insert,erase,get都是logn的

就是翻转不行,不是自己手写的打不了标记啊!!

怎么办?

答:同时维护一正一反两个rope……反转即交换两个子串……Orz……

区间循环位移?简单,拆成多个子串连起来就好了……

区间a变b b变c c变d …… z变a? 呃……维护26个rope?

区间和?滚蛋,那是线段树的活

区间kth?sorry,与数值有关的操作rope一概不支持……

5555 维修数列只能自己写了……

最后的Hint: 

rope的部分简单操作

函数 功能
push_back(x) 在末尾添加x
insert(pos,x) 在pos插入x
erase(pos,x) 从pos开始删除x个
replace(pos,x) 从pos开始换成x
substr(pos,x) 提取pos开始x个
at(x)/[x] 访问第x个元素

友情提示:cena不支持rope



你可能感兴趣的:(stl,STL,数据,树形结构,算法,库)