【题目描述】
早苗入手了最新的高级打字机。最新款自然有着与以往不同的功能,那就是它具备撤销功
能,厉害吧。
请为这种高级打字机设计一个程序,支持如下 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;
struct oppo {
    int to,next;
} rood[100005];
vector < int > q[100005];
int tot_q,ans[100005],a,n,tot,head[100005],all;
char T,t,sc[100005],v[100005],k[100005];
void add(int u,int v) {
    rood[++all].to=v;
    rood[all].next=head[u];
    head[u]=all;
}
void dfs(int x,int tot) {
    if(v[x]||x==0)    k[tot]=v[x];
    else    tot--;
    if(q[x].size())
        for(int i=0; i<q[x].size(); i++)
            sc[q[x][i]]=k[ans[q[x][i]]];
    for(int i=head[x]; i; i=rood[i].next)
        dfs(rood[i].to,tot+1);//向下搜索
}
int main() {
    freopen("a.in","r",stdin);
    freopen("c.out","w",stdout);
    cin>>n;
    for(int i=1; i<=n; i++) {
        cin>>T;
        if(T=='T') {
            cin>>t;
            v[++tot]=t;
            add(tot-1,tot);
        } else if(T=='U') {
            cin>>a;
            ++tot;
            add(tot-a-1,tot);
        } else if(T=='Q') {
            cin>>a;
            q[tot].push_back(++tot_q);
            ans[tot_q]=a;
        }
    }
    dfs(0,0);
    for(int i=1; i<=tot_q; i++)
        cout<<sc[i]<<endl;
    return 0;
}