请为这种高级打字机设计一个程序,支持如下 3 种操作:
1.T x:Type 操作,表示在文章末尾打下一个小写字母 x。
2.U x:Undo 操作,表示撤销最后的 x 次修改操作。
3.Q x:Query 操作,表示询问当前文章中第 x 个字母并输出。请注意 Query 操作并不算修改操作。 文章一开始可以视为空串。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
const int N = 1e5+5;
inline int read() {
int x=0,f=1;char C=getchar();
while(C<'0'||C>'9'){if(C=='-') f=-1;C=getchar();}
while(C>='0'&&C<='9') x=(x<<3)+(x<<1)+(C^48),C=getchar();
return x*f;
}
inline ll rd() {
ll x=0,f=1;char C=getchar();
while(C<'0'||C>'9'){if(C=='-') f=-1;C=getchar();}
while(C>='0'&&C<='9') x=(x<<3)+(x<<1)+(C^48),C=getchar();
return x*f;
}
inline char get(){
char C = getchar();
while((C<'a'||C>'z')&&(C<'A'||C>'Z')){C = getchar();}
return C;
}
int n, x, ops, rt, cnt;
char op, c;
int RT[N], L[N<<5], R[N<<5], sum[N<<5];
int build(int l, int r)
{
int rt = ++cnt;
int mid = (l+r)>>1;
if (l < r)
{
L[rt] = build(l, mid);
R[rt] = build(mid+1, r);
}
return rt;
}
int type(int pre, int l, int r, int pos)
{
int rt = ++cnt;
L[rt] = L[pre];
R[rt] = R[pre];
sum[rt] = sum[pre]+1;
int mid = (l+r)>>1;
if (l < r)
{
if (pos <= mid) L[rt] = type(L[pre], l, mid, pos);
else R[rt] = type(R[pre], mid+1, r, pos);
}
return rt;
}
int query(int rt, int l, int r, int pos)
{
if (l == r)
return l;
int x = sum[L[rt]];
int mid = (l+r)>>1;
if (pos <= x) return query(L[rt], l, mid, pos);
else return query(R[rt], mid+1, r, pos-x);
}
signed main()
{
n = read();
RT[0] = build('a', 'z');
for (int i = 1; i <= n; i++)
{
op = get();
if (op == 'T')
{
c = get();
ops++;
RT[ops] = type(RT[ops-1], 'a', 'z', c);
}
else if (op == 'U')
{
x = read();
ops++;
RT[ops] = RT[ops-x-1];
}
/*
else if (op == 'P')
{
for (int j = 1; j <= sum[RT[ops]]; j++)
cout << (char)query(RT[ops], 'a', 'z', j);
cout << endl;
}
*/
else
{
x = read();
cout << (char)query(RT[ops], 'a', 'z', x) << endl;
}
}
return 0;
}