Problem 1 高级打字机(type.cpp/c/pas)
【题目描述】
早苗入手了最新的高级打字机。最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧。
请为这种高级打字机设计一个程序,支持如下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挑战>
必须使用在线算法完成该题。
这题要用字典树(Tries)
还有msm(倍增算法)
另外 补充一点
char s[0] 或者 char
scanf("%s",s)
这句会存不下"\0"
因此会把正在循环的自变量i 变成 0
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<cmath> #include<vector> #include<cctype> using namespace std; #define MAXN (100000+10) #define LOGMAXN (16+10) int n,tot=0; struct Tnode { int deep,f[LOGMAXN]; char edge; Tnode() { memset(f,0,sizeof(f)); deep=-1; edge='\0'; } Tnode(char _edge,int _fa,int _deep) { memset(f,0,sizeof(f)); f[0]=_fa; edge=_edge; deep=_deep; } int logdeep() { return int(trunc(log(deep)/log(2))); } }node[MAXN]; int log2(int a) { return int(trunc(log(a)/log(2))); } void msm(Tnode &a) { int n=a.logdeep(); // if (n==1) return; for (int i=1;i<=n;i++) { a.f[i]=node[a.f[i-1]].f[i-1]; } } void type() { char c; scanf("%s",&c); tot++; node[tot]=Tnode(c,tot-1,node[tot-1].deep+1); msm(node[tot]); } void quere() { int p; scanf("%d",&p); Tnode now=node[tot]; p=now.deep+1-p; //第i's 祖先 while (p) { int i=log2(p); p-=(1<<i); now=node[now.f[i]]; } printf("%c\n",now.edge); } void undo() { int p; scanf("%d",&p); tot++; node[tot]=node[tot-1-p]; } int main() { freopen("type.in","r",stdin); freopen("type.out","w",stdout); scanf("%d",&n); node[0]=Tnode(); for (int ii=1;ii<=n;ii++) { // printf("%d\n",ii); char s[10]; // printf("%d\n",ii); scanf("%s",s); // printf("%d\n",ii); // while(1); switch(s[0]) { case 'T':type();break; case 'U':undo();break; case 'Q':quere();break; } } // while (1); return 0; }