20211228 [搜索、栈、版本树][P1383]高级打字机
考虑每次操作都按顺序建立一个版本,撤销也算
则撤销x步其实就是回退x步
借此可以建立一条边,由回退的位置直接指向当前位置
于是成了一棵树,在树上的每一条链上都不会有撤销
相当于把所有的撤销操作处理成了非线性的树形结构
于是可以一边搜索一边用栈去模拟
在输入时要记录一下哪些点上有询问,输出时按照顺序输出,所以要记录询问的时间
注意某些点上可能有多个点
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define maxn 200039
using namespace std;
int head[maxn], K, top;
char stack[maxn], ans[maxn];
struct FLY{
int to, nex;
char s;
}edges[maxn];
struct QUA{
int num, val;
char ans;
bool operator < (const QUA& b){
return this->num < b.num;
}
};
vector<QUA> qua[maxn];
void add(int from, int to){
edges[++K].to = to;
edges[K].nex = head[from];
head[from] = K;
}
int M, cnt, qua_cnt, v;
char opt, val, s[maxn];
void dfs(int u, int top){
if(s[u])stack[top] = s[u]; //不为空则谁说明是插入操作
for(int i = head[u]; i!=-1; i = edges[i].nex){
v = edges[i].to;
if(s[u])dfs(v, top+1); else dfs(v, top); //空的时候栈里不加东西
}
if(qua[u].size())
for(int i = 0; i < qua[u].size(); i++)
ans[qua[u][i].num] = stack[qua[u][i].val];
}
int main(){
//freopen("1.in", "r", stdin);
memset(head, -1, sizeof(head));
scanf("%d", &M);
add(0, 1);
while(M--){
scanf("%s", &opt);
if(opt=='T'){
scanf("%s", &val);
s[++cnt] = val;
add(cnt-1, cnt);
}
else if(opt=='Q'){
int val;
scanf("%d", &val);
qua[cnt].push_back((QUA){++qua_cnt, val}); //注意可能多个询问,所以要动态数组
}
else{
int val;
scanf("%d", &val);
++cnt;
add(cnt-val-1, cnt);
}
}
dfs(0, 1);
for(int i = 1; i < qua_cnt+1; i++)
printf("%c\n", ans[i]);
return 0;
}