[入门组模拟赛]高级打字机
题目描述
早苗入手了最新的高级打字机。最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧。
请为这种高级打字机设计一个程序,支持如下3种操作:
1.T x:在文章末尾打下一个小写字母x。(type操作)
2.U x:撤销最后的x次修改操作。(Undo操作)
(注意Query操作并不算修改操作)
3.Q x:询问当前文章中第x个字母并输出。(Query操作)
文章一开始可以视为空串。
输入
第1行:一个整数n,表示操作数量。
以下n行,每行一个命令。保证输入的命令合法。
输出
每行输出一个字母,表示Query操作的答案。
样例输入
7 T a T b T c Q 2 U 2 T c Q 2
样例输出
b c
提示
对于20%的数据 n<=200;
对于50%的数据 n<=100000;保证Undo操作不会撤销Undo操作。
对于100%的数据 n<=100000;Undo操作可以撤销Undo操作。
#include<bits/stdc++.h> using namespace std; const int N=100001; int cnt,n,w,f[N][23],g[N][23],close[N],head[N],num[N]; char s[10],c[10],a[N]; void insert() { num[cnt]=num[cnt-1]+1; if(a[cnt-1]=='U') close[cnt]=close[cnt-1]; else close[cnt]=cnt-1; if(a[cnt-1]=='U') f[cnt][0]=close[cnt-1]; else f[cnt][0]=cnt-1; head[cnt]=cnt-1; for(int i=1;i<=20;i++) f[cnt][i]=f[f[cnt][i-1]][i-1]; g[cnt][0]=cnt-1; for(int i=1;i<=20;i++) g[cnt][i]=g[g[cnt][i-1]][i-1]; } void Undo(int x) { x--; int now=cnt; a[++cnt]='U'; for(int i=20;i>=0;i--) if((1<<i)<=x) { x-=(1<<i); now=g[now][i]; } now--; head[cnt]=now; num[cnt]=num[now]; if(a[now]=='U') close[cnt]=close[now]; else close[cnt]=now; if(a[now]=='U') f[cnt][0]=close[now]; else f[cnt][0]=now; for(int i=1;i<=20;i++) f[cnt][i]=f[f[cnt][i-1]][i-1]; g[cnt][0]=cnt-1; for(int i=1;i<=20;i++) g[cnt][i]=g[g[cnt][i-1]][i-1]; } int main() { scanf("%d",&n); a[0]='A'; close[0]=0; for(int i=1;i<=n;i++) { scanf("%s",s); if(s[0]=='T') { scanf("%s",c); a[++cnt]=c[0]; insert(); continue; } if(s[0]=='U') { scanf("%d",&w); Undo(w); continue; } if(s[0]=='Q') { scanf("%d",&w); w=num[cnt]-w+1; if(w<=0) w=1; if(a[cnt]!='U') w--; int now=cnt; for(int i=20;i>=0;i--) if((1<<i)<=w) { w-=(1<<i); now=f[now][i]; } printf("%c\n",a[now]); } } return 0; }