您的位置:首页 > 其它

高级打字机

2016-06-20 16:37 155 查看
【题目描述】

早苗入手了最新的高级打字机。最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧。

请为这种高级打字机设计一个程序,支持如下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

【数据范围】

对于40%的数据 n<=200;

对于100%的数据 n<=100000;保证Undo操作不会撤销Undo操作。

<高级挑战>

对于200%的数据 n<=100000;Undo操作可以撤销Undo操作。

<IOI挑战>

必须使用在线算法完成该题。

题解:

因为Undo操作只能撤销Type操作,所以Undo x 实际上就是删除文章末尾x个字母。用一个栈即可解决(每个字母最多进出一次)。

<高级挑战> (考虑到部分选手水平较高,故设此附加题)

本题虽为2012年IOI的题目,但只要使用离线算法,就成为只需noip级别编程水平的题目了。

以下声明一些定义:(对于此类题目以及各种可持久化数据结构的离线解法的思考很有帮助)

版本:接受第1--i个修改操作(包含Type和Undo)后的状态称为版本i。版本0为初始状态。

版本链:一般的数据结构题目只有各种修改命令(比如本题的Type操作),那么所有版本就会呈链状排列。

#include<cstdio>
#include<iostream>
using namespace std;
#define N 10000100
int root
,len
,lc
,rc
,tot;
char s[N*2];
inline void ins(int &y,int x,int l,int r,int pos,char c)
{
y=++tot;
if(l==r) {s[y]=c;return ;}
else
{
int mid=l+r>>1;lc[y]=lc[x];rc[y]=rc[x];
if(pos<=mid) ins(lc[y],lc[x],l,mid,pos,c);
else ins(rc[y],rc[x],mid+1,r,pos,c);
}
}
inline void query(int y,int l,int r,int pos)
{
if(l==r){printf("%c\n",s[y]);return ;}
else
{
int mid=l+r>>1;
if(pos<=mid) query(lc[y],l,mid,pos);
else query(rc[y],mid+1,r,pos);
}
}
int main()
{
int n,cnt=0,lm=1,rm=100000;
scanf("%d",&n);
for(int i=1,x;i<=n;i++)
{
char cmd[2],ch[2];
scanf("%s",cmd);
if(cmd[0]=='T')
{
scanf("%s",ch);cnt++;len[cnt]=len[cnt-1]+1;
ins(root[cnt],root[cnt-1],lm,rm,len[cnt],ch[0]);
}
else if(cmd[0]=='U')
{
scanf("%d",&x);cnt++;
root[cnt]=root[cnt-x-1];
len[cnt]=len[cnt-x-1];
}
else scanf("%d",&x),query(root[cnt],lm,rm,x);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: