目录:
题目:
分析:
属于比较裸的可持久化数据结构题。
我的做法是使用主席树,主席树可以解决对一个数列(或什么别的数据结构)进行如下操作的问题:
1.修改某个历史版本,并将修改完的版本作为新的版本。
2.询问某个历史版本上的值。
题目要求维护文章的第x个字符,我们知道在主席树中,叶子节点记录的就是某一个位置的数据,于是T操作可以通过修改一条链然后新建版本实现。
那么U操作呢?设新建的版本标号为
,那么撤销最后x次操作也就是回到标号为
的版本,将
版本的根设为
的根即可。
这么一来,Q操作就好做了,也就是询问x位置的值是什么,一路递归至叶子结点即可。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
int tot=0,len[100007],cnt=0;
char c;
struct Tree
{
int rt[100007],ls[(100007)<<5],rs[(100007)<<5];
char val[(100007)<<5];
void build(int &rt,int fa,int l,int r,int po)
{
if(!rt) rt=++tot;//动态开点
if(l==r)
{
val[rt]=c;
return;
}
int mid=(l+r)>>1;
if(po<=mid)
{
rs[rt]=rs[fa];
build(ls[rt],ls[fa],l,mid,po);
}
if(mid+1<=po)
{
ls[rt]=ls[fa];
build(rs[rt],rs[fa],mid+1,r,po);
}
}
char q(int rt,int l,int r,int po)
{
if(l==r) return val[rt];
int mid=(l+r)>>1;
if(po<=mid)
return q(ls[rt],l,mid,po);
if(mid+1<=po)
return q(rs[rt],mid+1,r,po);
}
}tree;
int main()
{
int n=read(),t;
for(int i=1;i<=n;i++)
{
cin>>c;
if (c=='T')
{
cin>>c;
len[++cnt]=len[cnt-1]+1;
tree.build(tree.rt[cnt],tree.rt[cnt-1],1,100007,len[cnt]);
}
else if (c=='U')
{
t=read();
len[++cnt]=len[cnt-t-1];
tree.rt[cnt]=tree.rt[cnt-t-1];
}
else
{
t=read();
cout<<tree.q(tree.rt[cnt],1,100007,t)<<endl;
}
}
return 0;
}