高级打字机
luogu 1383
题目大意:
有三种操作:添加一个字符(更改操作),撤回前iii步步更改操作(更改操作,可以撤回自己),输出某一位的字符,现在要按要求输出字符
原题:
题目描述
早苗入手了最新的高级打字机。最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧。
请为这种高级打字机设计一个程序,支持如下3种操作:
1.T x:在文章末尾打下一个小写字母x。(type操作)
2.U x:撤销最后的x次修改操作。(Undo操作)
3.Q x:询问当前文章中第x个字母并输出。(Query操作)
文章一开始可以视为空串。
输入输出格式
输入格式:
第1行:一个整数n,表示操作数量。
以下n行,每行一个命令。保证输入的命令合法。
输出格式:
每行输出一个字母,表示Query操作的答案。
输入输出样例
输入样例#1:
7
T a
T b
T c
Q 2
U 2
T c
Q 2
输出样例#1:
b
c
说明
【数据范围】
对于20%的数据 n<=200;
对于50%的数据 n<=100000;保证Undo操作不会撤销Undo操作。
<高级挑战>
对于100%的数据 n<=100000;Undo操作可以撤销Undo操作。
<IOI挑战>
必须使用在线算法完成该题。
解题思路:
把每一次更改操作当做一个点,当撤销时就连接撤销到的点,然后输出就取最近一次更改操作的结果
代码:
#include<map>
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,o,k,y,w,tot,head[100005],ans[100005];
char x,t[100005],c[100005];
map<int, map<int,int> >p;
struct rec
{int to,next;
}a[100005];
void dfs(int dep,int lon)
{for (int i=head[dep];i;i=a[i].next)//撤销的dfs(a[i].to,lon);if (t[dep]) c[lon]=t[dep],dfs(dep+1,lon+1);//添加字符for (int i=1;i<=p[dep][0];++i)ans[p[dep][i]]=c[ans[p[dep][i]]];//记录
}
int main()
{scanf("%d",&n);for (int i=1;i<=n;++i){cin>>x;if (x=='T') cin>>t[k++],o=k;else if (x=='U'){k++;scanf("%d",&y);a[++tot].to=k;//连接a[tot].next=head[k-y-1];head[k-y-1]=tot;o=k;//更新}if (x=='Q'){scanf("%d",&y);p[o][++p[o][0]]=++w;//连接的是第几个输出ans[w]=y;//初值设为他要求的字符是第几个,然后记录答案时直接带替即可}}dfs(0,1);for (int i=1;i<=w;++i)putchar(ans[i]),putchar(10);//输出
}