知识点 - 持久化序列
解决问题类型:
您需要维护一个序列,其中需要提供以下操作:
- 插入一个数到序列的第 t 版本使其成为序列的第 k 项,这个数为 x;
- 删除序列的第 t 版本的第 k 项;
- 查询序列的第 t 版本的第 k 项。
复杂度:
查找结点 O ( l o g N ) O(logN) O(logN)
例题
代码
- 持久化 treap
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define ptt pair<treap*,treap*>
namespace IO{
char ss[1<<17],*A=ss,*B=ss;
inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
template<class T>inline void Rd(T&x){
char c;T y=1;while(c=gc(),!isdigit(c)&&c!=-1);x=c-48;
while(c=gc(),isdigit(c))x=x*10+c-48;x*=y;
}
char sr[1<<21],z[20];int C=-1,Z;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
template<class T>inline void Wt(T x){
if(C>1<<20)Ot();
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
}
template<class T>inline bool chkmin(T&a,T const&b){return a>b?a=b,true:false;}
template<class T>inline bool chkmax(T&a,T const&b){return a<b?a=b,true:false;}
const int M=300005;
struct treap{
int val,sz,pri;
treap *ls,*rs;
void* operator new(size_t _){
static treap Pool[M*25],*allc=Pool;
return allc++;
}
void up(){
sz=1;
if(ls!=nullptr) sz+=ls->sz;
if(rs!=nullptr) sz+=rs->sz;
}
}*root[M];
inline int SZ(treap *p){return p==nullptr?0:p->sz;}
treap *merge(treap *p,treap *q){
if(p==nullptr) return q;
if(q==nullptr) return p;
if(p->pri<q->pri){
p=new treap(*p);
p->rs=merge(p->rs,q);
return p->up(),p;
}else{
q=new treap(*q);
q->ls=merge(p,q->ls);
return q->up(),q;
}
}
ptt split(treap *p,int k){
if(p==nullptr) return {nullptr,nullptr};
p=new treap(*p);
int sz=SZ(p->ls);
if(sz<k){
ptt o=split(p->rs,k-sz-1);
p->rs=o.x,p->up();
return {p,o.y};
}else{
ptt o=split(p->ls,k);
p->ls=o.y,p->up();
return {o.x,p};
}
}
treap* insert(treap *p,int k,int x,int w){
if(p==nullptr) return new(treap){x,1,w,nullptr,nullptr};
p=new treap(*p);
int sz=SZ(p->ls);
if(w<p->pri){
ptt o=split(p,k-1);
*p=(treap){x,1,w,o.x,o.y};
}else if(sz+1<k) p->rs=insert(p->rs,k-sz-1,x,w);
else p->ls=insert(p->ls,k,x,w);
if(p!=nullptr) p->up();
return p;
}
treap* remove(treap *p,int k){
int sz=SZ(p->ls);
p=new treap(*p);
if(sz+1==k) p=merge(p->ls,p->rs);
else if(sz<k) p->rs=remove(p->rs,k-sz-1);
else p->ls=remove(p->ls,k);
if(p!=nullptr) p->up();
return p;
}
int kth(treap *p,int k){
int res;
while(p!=nullptr){
int sz=SZ(p->ls);
if(sz<k) res=p->val,p=p->rs,k-=sz+1;
else p=p->ls;
}
return res;
}
int main(){
srand(time(NULL));
int n,i=0;
IO::Rd(n);
while(n--){
int op,k,x,t;
IO::Rd(op),IO::Rd(t),IO::Rd(k);
if(op==1) IO::Rd(x),root[++i]=insert(root[t],k,x,rand());
if(op==2) root[++i]=remove(root[t],k);
if(op==3) IO::Wt(kth(root[t],k));
}
IO::Ot();
return 0;
}
- rope
#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
const int MaxN(300007);
rope<int> *H[MaxN];
int main()
{
int K=0,M,k,x,t,opt;
H[0]=new rope<int>();
scanf("%d",&M);
while(M--)
{
scanf("%d%d%d",&opt,&t,&k);
if(opt==1)
{
scanf("%d",&x);
H[++K]=new rope<int>(*H[t]);
H[K]->insert(k-1,x);
}
if(opt==2)
{
H[++K]=new rope<int>(*H[t]);
H[K]->erase(k-1,1);
}
if(opt==3) printf("%d\n",H[t]->at(k-1));
}
return 0;
}