Description
早苗入手了最新的高级打字机。最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧。
请为这种高级打字机设计一个程序,支持如下3种操作:
T x:在文章末尾打下一个小写字母x。(type操作)
U x:撤销最后的x次修改操作。(Undo操作)(注意Query操作并不算修改操作)
Q x:询问当前文章中第x个字母并输出。(Query操作)文章一开始可以视为空串。
Input
第1行:一个整数n,表示操作数量。
以下n行,每行一个命令。保证输入的命令合法。
Output
每行输出一个字母,表示Query操作的答案。
Sample Input
7
T a
T b
T c
Q 2
U 2
T c
Q 2
Sample Output
b
c
Data Constraint
对于40%的数据 n<=200;
对于100%的数据 n<=100000;保证Undo操作不会撤销Undo操作。
<高级挑战>
对于200%的数据 n<=100000;Undo操作可以撤销Undo操作。
The Solution
裸体一道,模板默写大会。。。
各种可持久化结构套上。。
以下是用可持久化线段树维护
CODE
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#define fo(i,a,b) for (int i=a;i<=b;i++)
#define N 1000005
using namespace std;
typedef long long ll;
int n,tot = 0,v = 0;
char Stack[N * 2];
int Root[N],Len[N];
struct node
{
int l,r;
}a[N * 2];
inline int read()
{
int x=0,w=1;
char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*w;
}
void Update(int &y,int x,int l,int r,int pos,char c)
{
y = ++ tot;
if (l == r) Stack[y] = c;
else
{
int mid = (l + r) >> 1;
a[y].l = a[x].l, a[y].r = a[x].r;
if (pos <= mid) Update(a[y].l,a[x].l,l,mid,pos,c);
else Update(a[y].r,a[x].r,mid + 1,r,pos,c);
}
}
void Query(int y,int l,int r,int pos)
{
if (l == r) printf("%c\n",Stack[y]);
else
{
int mid = (l + r) >> 1;
if (pos <= mid ) Query(a[y].l,l,mid,pos);
else Query(a[y].r,mid + 1,r,pos);
}
}
int main()
{
n = read();
while (n --)
{
char cmd[2],s[2];
scanf("%s",cmd);
if (cmd[0] == 'T')
{
scanf("%s",s);
Len[++ v] = Len[v - 1] + 1;
Update(Root[v],Root[v - 1],1,N,Len[v],s[0]);
}
else
if (cmd[0] == 'U')
{
int x = read();
Root[++ v] = Root[v - x -1];
Len[v] = Len[v - x - 1];
}
else Query(Root[v],1,N,read());
}
}