stl之rope大法好及可持久化并查集用法

rope大法好

rope是c++的stl库中的一个叫做可持久化平衡树的结构,这个神奇的结构支持什么功能呢?看测试代码:

#include<iostream>
#include<cstdio>
#include<ext/rope>//头文件
using namespace std;
using namespace __gnu_cxx;//使用rope要加这句
#define LL long long
rope<char> tmp;
char test[100]="I am cute.";
int main(){
    int i,j;
    tmp.push_back('h');//在末尾插入一个字符
    cout<<tmp<<endl;
    tmp.insert(1,'e');//在第pos位置上插入一串/个字符
    tmp.insert(2," is gaood");
    cout<<tmp<<endl;
    tmp.erase(7,2);//从第7位开始连续删除两个字符
    cout<<tmp<<endl;
    tmp.copy(6,2,test);//将从第6位开始的两个字符插入到test开头
    cout<<tmp<<"           "<<test<<endl;
    tmp.replace(1,'i');tmp.replace(0,"bosh");//修改pos位置上的字符为...
    cout<<tmp<<endl;
    cout<<tmp.substr(0,5)<<endl;//从第0位开始提取5个字符
    cout<<tmp.substr(9)<<endl;//提取第9个字符(默认提取一个)
    cout<<tmp.at(3)<<endl;//访问第3个字符
    return 0;
}

测试结果:

h
he is gaood
he is god
he is god           goam cute.
boshi is god
boshi
g
h

《OI·创世纪》为了报复boshi大佬而重新修订版(现已删除)

rope的可持久化

那么rope怎么实现可持久化???
很简单,建一堆rope即可。有时候也是通过转化指针来实现更快地查询历史版本的。总之rope实现历史版本很快的
那让我们愉快地做一道模板题吧:
Uva12538
支持三种操作:
1.在pos位置插入一串字符
2.从pos位置开始删除长度为l的字符串
3.查询第v个历史版本中从pos位置开始的长度为l的字符串(此操作没有产生新的历史版本)
然后询问进行了加密:pos,l,v均需要减去d,d的定义:所有询问中输出的字符‘c’的数量和。

#include<iostream>
#include<cstdio>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define LL long long
rope<char> tmp,his[50005],kl;
char ch[205];
int n,d,cn;
int main(){
    int i,bj,x,y,v;
    scanf("%d",&n);
    for(i=1;i<=n;++i){
        scanf("%d",&bj);
        if(bj==1){
            scanf("%d%s",&x,ch);
            x-=d;tmp.insert(x,ch);//插入
            his[++cn]=tmp;
        }
        else if(bj==2){
            scanf("%d%d",&x,&y);
            x-=d,y-=d;tmp.erase(x-1,y);//删除
            his[++cn]=tmp;
        }
        else {
            scanf("%d%d%d",&v,&x,&y);
            v-=d,x-=d,y-=d;
            kl=his[v].substr(x-1,y);//提取
            d+=count(kl.begin(),kl.end(),'c');
            cout<<kl<<endl;
        }
    }
    return 0;
}

可持久化并查集

瞎哔哔了这么多,我到底要说什么呢?——就是可持久化并查集!!!
因为你想,并查集是那么优美而精简的数据结构,达成可持久化就要用麻烦的可持久化线段树/平衡树维护,然而可持久化线段树,即主席树是可以打的很短的,本蒟蒻就打过很短的,但是现在本蒟蒻已经废了,打不出主席树了…是不是非常地令人不爽?还好有rope!!!
例题:暴力一点!直接上bzoj3674
事实上将父亲可持久化就可以了,具体看代码吧,实现还挺简单的….但是——直接暴力rope容易 被查水表 MLE或者RE…
那怎么办呢?其实很简单,如果当前版本没有发生修改,没有必要整体替换一个新版本。我们先开一个数组id表示每一个询问所使用的坂本版本,只有当发生修改时才需要一个新版本。这样空间节省了一半,可以AC!!!
不过慢的死就是了

#include<iostream>
#include<cstdio>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define LL long long
int n,m,ans;
const int N=200005;
rope<int> *f[N];
int a[N],id[N];//id:每一次查询所使用的版本
int find(int t,int x){
    if(f[t]->at(x)==x)return x;
    f[t]->replace(x,find(t,f[t]->at(x)));
    return f[t]->at(x);
}
int main(){
    int i,bj,x,y,r1,r2,t=0;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;++i)a[i]=i;
    f[0]=new rope<int>(a,a+1+n);
    for(i=1;i<=m;++i){
        scanf("%d",&bj);
        if(bj==1){
            scanf("%d%d",&x,&y);
            x^=ans,y^=ans;
            r1=find(t,x),r2=find(t,y);
            if(r1!=r2){//需要修改,开新版本
                f[i]=new rope<int>(*f[t]);
                f[i]->replace(r1,r2),t=i;
            }
        }
        else if(bj==2){scanf("%d",&x),t=id[x^ans];}//直接更改t
        else {
            scanf("%d%d",&x,&y);
            if(find(t,x^ans)==find(t,y^ans))ans=1;
            else ans=0;
            printf("%d\n",ans);
        }
        id[i]=t;//更新这一次询问后使用的版本
    }
    return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值