P1383 高级打字机

    • 18通过
    • 118提交
  • 题目提供者yeszy
  • 标签倍增图论高级数据结构福建省历届夏令营
  • 难度省选/NOI-

提交该题 讨论 题解 记录

最新讨论

  • 暂时没有讨论

题目描述

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

请为这种高级打字机设计一个程序,支持如下3种操作:

1.T x:在文章末尾打下一个小写字母x。(type操作)

2.U x:撤销最后的x次修改操作。(Undo操作)

(注意Query操作并不算修改操作)

3.Q x:询问当前文章中第x个字母并输出。(Query操作)

文章一开始可以视为空串。

输入输出格式

输入格式:

第1行:一个整数n,表示操作数量。

以下n行,每行一个命令。保证输入的命令合法。

输出格式:

每行输出一个字母,表示Query操作的答案。

输入输出样例

输入样例#1:

7
T a
T b
T c
Q 2
U 2
T c
Q 2
输出样例#1:

b
c

说明

【数据范围】

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

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

<高级挑战>

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

<IOI挑战>

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

50分代码(栈模拟):

#include<cstdio>
using namespace std;
#define N 51000
int top,T;
char st[N];
int main(){
scanf("%d",&T);
while(T--){
char c1[],c2[];int x;
scanf("%s",c1);
if(c1[]=='T'){
scanf("%s",c2);
st[++top]=c2[];
}
if(c1[]=='U'){
scanf("%d",&x);
top-=x;
}
if(c1[]=='Q'){
scanf("%d",&x);
printf("%c\n",st[x]);
}
}
return ;
}

题解:

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

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

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

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

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

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

这种情况下只需要设计一个合理的数据结构依次执行操作即可。

版本树:Undo x撤销最近的x次修改操作,实际上就是当前版本还原为x次操作前的版本,换句话说,版本i = 版本i-x-1。

如图所示,所有版本呈树状排列,版本0为根。

读入所有操作并建树,对这颗版本树按欧拉序求出所有版本。上图中就是按0->1->4...4->1->0->2->3->2->0的顺序遍历,同样使用栈就能计算出所有的版本,然后在对应的版本上解决询问即可。

到此,就得到了时空复杂度均为O(n)的离线算法。

能解决这类题目的条件是:

1.允许使用离线算法,进而求出版本树,并允许把询问挂到树的节点上。

2.所有操作都是可逆的。只有所有操作都是可逆的,才能按欧拉序依次求出各版本。如本题的Type操作的逆操作就是弹出栈顶,Undo操作则根本不需要修改(Undo前后2个版本相同)。

相关题目:crisis 60% (2012 国家集训队hw2出题互测\卓亮)

<IOI挑战>

Trie+倍增法寻祖                                       O(nlogn)

各种可持久化数据结构:可持久化块状数组                O(nsqrtn)

可持久化跳表(与Trie解法相近) O(nlogn)

......

因超出noip范围不做更多展开。

AC代码(手写主席树):

#include<cstdio>
using namespace std;
const int R=1e5,N=(R+)*;
int n,m,now,sz,root[R+],ls[N],rs[N],len[N];
char s[N];
inline int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void insert(int &k,int last,int l,int r,int pos,int c){
k=++sz;
if(l==r){s[k]=c;return ;}
ls[k]=ls[last];
rs[k]=rs[last];
int mid=l+r>>;
if(pos<=mid) insert(ls[k],ls[last],l,mid,pos,c);
else insert(rs[k],rs[last],mid+,r,pos,c);
}
void query(int &k,int last,int l,int r,int pos){
if(l==r){putchar(s[k]);putchar('\n');return ;}
int mid=l+r>>;
if(pos<=mid) query(ls[k],ls[last],l,mid,pos);
else query(rs[k],rs[last],mid+,r,pos);
}
int main(){
n=read();
for(int i=,x;i<=n;i++){
char op=,ch=;
for(;op<'A'||op>'Z';op=getchar());
if(op=='T'){
for(;ch<'a'||ch>'z';ch=getchar());
now++;
len[now]=len[now-]+;
insert(root[now],root[now-],,R,len[now],ch);
}
else if(op=='U'){
x=read();
now++;
root[now]=root[now-x-];
len[now]=len[now-x-];
}
else x=read(),query(root[now],root[now-],,R,x);
}
return ;
}

AC代码(rope标程):

#include<cstdio>
#include<iostream>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
const int maxn=1e5+;
rope<char> *his[maxn];
int n,m;
inline char getC(){
for(register char ch=getchar();;ch=getchar()) if((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z')) return ch;
}
inline int getint(){
register int x=,f=;
register char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int main(){
n=getint();
his[]=new rope<char>();
for(int i=;i<=n;i++){
char opt=getC();
if(opt=='T'){
m++;
his[m]=new rope<char>(*his[m-]);//就是这一句!它可以实现O(1)的拷贝历史版本,由于rope的底层是平衡树,copy时copy根节点就行了;用它就可以轻松实现可持久化数组
char x=getC();
his[m]->push_back(x);
}else if(opt=='U'){
int x=getint();
m++;
his[m]=new rope<char>(*his[m-x-]); }else if(opt=='Q'){
int x=getint()-;
putchar(his[m]->at(x));
putchar('\n');
}
}
return ;
}

洛谷 P1383 高级打字机==codevs 3333 高级打字机的更多相关文章

  1. 洛谷P1395 会议(CODEVS.3029.设置位置)(求树的重心)

    To 洛谷.1395 会议 To CODEVS.3029 设置位置 题目描述 有一个村庄居住着n个村民,有n-1条路径使得这n个村民的家联通,每条路径的长度都为1.现在村长希望在某个村民家中召开一场会 ...

  2. codevs 3333 高级打字机

    3333 高级打字机   题目描述 Description 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧. 请为这种高级打字机设计一个程序,支持如下3种操作 ...

  3. 洛谷P1432 倒水问题(CODEVS.1226)

    To 洛谷.1432 倒水问题 题目背景 In the movie "Die Hard 3", Bruce Willis and Samuel L. Jackson were co ...

  4. 洛谷 P2155 BZOJ 2186 codevs 2301 [SDOI2008]沙拉公主的困惑

    题目描述 大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票.房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的 ...

  5. 洛谷P1650赛马与codevs 2181 田忌赛马

    洛谷P1650 赛马 题目描述 我国历史上有个著名的故事: 那是在2300年以前.齐国的大将军田忌喜欢赛马.他经常和齐王赛马.他和齐王都有三匹马:常规马,上级马,超级马.一共赛三局,每局的胜者可以从负 ...

  6. 洛谷 P1383 codevs 3333 高级打字机

    题目描述 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧. 请为这种高级打字机设计一个程序,支持如下3种操作: 1.T x:在文章末尾打下一个小写字母x.(t ...

  7. 【洛谷P1383 高级打字机】

    题目描述 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧. 请为这种高级打字机设计一个程序,支持如下3种操作: 1.T x:在文章末尾打下一个小写字母x.(t ...

  8. 洛谷 P1262 间谍网络==Codevs 4093 EZ的间谍网络

    4093 EZ的间谍网络 时间限制: 10 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 由于外国间谍的大量渗入,国家安全正处于高度的危机之中.如果A间谍手中掌握着关于B ...

  9. 洛谷——P1002 过河卒||codevs——T1010 过河卒

    https://www.luogu.org/problem/show?pid=1002#sub||http://codevs.cn/problem/1010/ 题目描述 棋盘上A点有一个过河卒,需要走 ...

随机推荐

  1. B5. Concurrent JVM 锁优化

    [概述] 高效并发是从 JDK1.5 到 JDK 1.6 的一个重要改进,HotSpot 虚拟机开发团队在这个版本上花费了大量的精力去实现各种锁优化技术,如适应性自旋(Adaptive Spining ...

  2. Go:map

    一.map的创建方式 func main() { // map创建方式1 // 声明后再make var stu1 map[int]string stu1 = make(map[int]string, ...

  3. Nginx(alias 和 root的区别)

    Nginx(alias 和 root的区别)1.alias 和 root 的区别: location /request_path/image { root /local_path/image/; } ...

  4. leetcode-88合并两个有序数组

    合并两个有序数组 思路:利用索引合并两个列表,排序.注意不需要返回值,只修改nums1 class Solution: def merge(self, nums1: List[int], m: int ...

  5. Android使用JDBC连接数据库

    连接数据库是安卓开发中几乎不可避免的一项工作,稍有规模的应用通常都需要使用数据库来存储用户数据.对于本地数据库当然可以使用sqlite,而对于多用户线上应用,则一般需要配备云端数据库.其中比较常用且开 ...

  6. Uva 1572 自组合

    贴个源码// UVa1572 Self-Assembly // Rujia Liu #include<cstdio> #include<cstring> #include< ...

  7. LeetCode 167. Two Sum II – Input array is sorted

    Given an array of integers that is already sorted in ascending order, find two numbers such that the ...

  8. 动态规划法解最长公共子序列<算法分析>

    一.实验内容及要求 1.要求按动态规划法原理求解问题: 2.要求在20以内整数随机产生两个序列数据: 3.要求显示随机产生的序列及最长公共子序列.二.实验步骤 1.随机产生数列: 2.输出随机序列:  ...

  9. Leetcode 143.重排链表

    重排链表 给定一个单链表 L:L0→L1→…→Ln-1→Ln ,将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→… 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换. 示 ...

  10. 转盘抽奖 canvas & 抽奖 H5 源码

    转盘抽奖 canvas https://github.com/givebest/wechat-turntalbe-canvas https://blog.givebest.cn/GB-canvas-t ...