题目描述得不够准确,撤销时,可以将之前的撤销操作同时撤销
这样题目就要求我们保留之前的所有数据,我们利用主席树维护一段字符串,长度为 1e5,假设全部是添加字符
设当前的根节点为 now
撤销操作相当于将之前的 now-x 节点复制过来,作为 now+1 根节点
添加操作在区间的末尾添加一个字符
查询操作,由于 s[i] 字符放在 i 位置,所以直接查询第 x 个位置的字符即可
const int N=1e5+5;
int n,m;
int i,j,k;
struct Node
{
int l,r;
char ch;
int sz;
}t[N<<5];
int root[N],tot=0;
void update(int now,int &p,int l,int r,int pos,char val)
{
p=++tot;
t[p]=t[now];
t[p].sz++;
if(l==r) t[p].ch=val;
else{
int mid=l+r>>1;
if(mid>=pos) update(t[now].l,t[p].l,l,mid,pos,val);
else update(t[now].r,t[p].r,mid+1,r,pos,val);
}
}
char query(int p,int l,int r,int pos)
{
if(l==r) return t[p].ch;
else{
int mid=l+r>>1;
if(mid>=pos) return query(t[p].l,l,mid,pos);
else return query(t[p].r,mid+1,r,pos);
}
}
signed main()
{
IOS;
while(cin>>n){
char ch,opt;
int x,now=0;
for(int i=1;i<=n;i++){
cin>>opt;
if(opt=='T'){
cin>>ch;
++now;
update(root[now-1],root[now],1,n,t[root[now-1]].sz+1,ch);
} else{
cin>>x;
if(opt=='U') root[++now]=root[now-x];
else if(opt=='Q') cout<<query(root[now],1,n,x)<<endl;
}
}
}
//PAUSE;
return 0;
}