洛谷传送门
思路:用主席树维护每个版本的线段树然后查询即可,注意题中给的撤销操作能撤销前面的撤销操作,那么我们干脆存一下每次插入或者插销完操作后对应的版本就行了,每次撤销更新的时候就找我们存下来的数组里面的版本
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int root[N];
struct xds
{
int l,r,sum;
char val;
}xd[64*N];
int tot;
int tot_2;
void build(int &rt,int l,int r)
{
if(!rt) rt=++tot;
if(l==r) return;
int mid=l+r>>1;
build(xd[rt].l,l,mid);
build(xd[rt].r,mid+1,r);
}
void motify(int pre,int &rt,int l,int r,int pos,char val)
{
if(!rt) rt=++tot;
xd[rt].sum=xd[pre].sum+1;
if(l==r)
{
xd[rt].val=val;
return;
}
int mid=l+r>>1;
if(pos<=mid)
{
xd[rt].r=xd[pre].r;
motify(xd[pre].l,xd[rt].l,l,mid,pos,val);
}
else
{
xd[rt].l=xd[pre].l;
motify(xd[pre].r,xd[rt].r,mid+1,r,pos,val);
}
}
char query(int rt,int l,int r,int pos)
{
// if(!rt) rt=++tot;
if(l==r) return xd[rt].val;
int mid=l+r>>1;
if(pos<=mid) return query(xd[rt].l,l,mid,pos);
else return query(xd[rt].r,mid+1,r,pos);
}
void solve(){
int n;
cin>>n;
vector<int>version;
version.push_back(0);
build(root[0],1,n);
int cur=0;
for(int i=1;i<=n;i++)
{
char s;
cin>>s;
if(s=='T')
{
char x;
cin>>x;
tot_2++;
motify(root[cur],root[tot_2],1,n,xd[root[cur]].sum+1,x);
cur=tot_2;
version.push_back(tot_2);
}
else if(s=='U')
{
int x;
cin>>x;
int len=version.size();
cur=version[len-x-1];
version.push_back(cur);
}
else
{
int x;
cin>>x;
cout<<query(root[cur],1,n,x)<<"\n";
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int T=1;
while(T--){solve();}
return 0;
}