P1383 高级打字机
Posted bigyellowdog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1383 高级打字机相关的知识,希望对你有一定的参考价值。
P1383 高级打字机
Description
早苗入手了最新的高级打字机。最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧。
请为这种高级打字机设计一个程序,支持如下3种操作:
1.T x:在文章末尾打下一个小写字母x。(type操作)
2.U x:撤销最后的x次修改操作。(Undo操作)
(注意Query操作并不算修改操作)
3.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 Size
【数据范围】
对于40%的数据 n<=200;
对于100%的数据 n<=100000;保证Undo操作不会撤销Undo操作。
<高级挑战>
对于200%的数据 n<=100000;Undo操作可以撤销Undo操作。
必须使用在线算法完成该题。
题解:
- 主席树。
- 一开始无脑水了个vector上去,80pts。爆空间了。如果全是插入操作的话,空间复杂度近似于O(n^2)。后来就敲了一发主席树就过了。原因是每次插入操作都只是开了一条链的空间而已。总体空间复杂度大概是O(nlogn)
(大概 - 具体思路比较简单,每一个时间戳建一棵树,拿个数组记录每棵树插入到第几个位置然后就在原树上插入;撤销直接rt[i]=rt[i-x];查询查就是了。
#include <iostream>
#include <cstdio>
#define N 100005
using namespace std;
struct T {int l,r,v;}t[N*32];
int n,dfn,dex;
int cnt[N],rt[N];
int build(int l,int r)
{
int p=++dex,mid=l+r>>1;
if(l==r) return p;
t[p].l=build(l,mid);
t[p].r=build(mid+1,r);
return p;
}
int upd(int lat,int l,int r,int pos,int val)
{
int p=++dex,mid=l+r>>1;
t[p]=t[lat];
if(l==r) {t[p].v=val;return p;}
if(pos<=mid) t[p].l=upd(t[lat].l,l,mid,pos,val);
else t[p].r=upd(t[lat].r,mid+1,r,pos,val);
return p;
}
int ask(int p,int l,int r,int pos)
{
if(l==r) return t[p].v;
int mid=l+r>>1;
if(pos<=mid) return ask(t[p].l,l,mid,pos);
return ask(t[p].r,mid+1,r,pos);
}
int main()
{
cin>>n;
rt[0]=build(1,n);
for(int i=1;i<=n;i++)
{
char c[3]; scanf("%s",c);
if(c[0]=='T') {
char x[3]; scanf("%s",x);
dfn++,rt[dfn]=upd(rt[dfn-1],1,n,cnt[dfn-1]+1,x[0]-'a'+1);
cnt[dfn]=cnt[dfn-1]+1;
}
else if(c[0]=='U') {
int x; scanf("%d",&x);
dfn++,rt[dfn]=rt[dfn-x-1];
cnt[dfn]=cnt[dfn-x-1];
}
else if(c[0]=='Q') {
int x; scanf("%d",&x);
printf("%c
",ask(rt[dfn],1,n,x)-1+'a');
}
}
return 0;
}
高级挑战>以上是关于P1383 高级打字机的主要内容,如果未能解决你的问题,请参考以下文章
洛谷 P1383 高级打字机==codevs 3333 高级打字机