[JZOJ 3794]. 【NOIP2014模拟8.20】高级打字机

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());
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值