高级打字机【主席树】【滚动数组】【块状链表】

题目大意:
一个计算机支持一下三中操作:
TT xx:在文章末尾打下一个小写字母xx
UU xx:撤销最后的xx次修改操作。
QQ xx:询问当前文章中第xx个字母并输出。
InputInput

7
T a
T b
T c
Q 2
U 2
T c
Q 2

OutputOutput

b
c

思路:
IOI题目。。。
正解是主席树(当然啦什么TrieTrie+倍增法寻祖,可持久化跳表,可持久化块状数组无敌的东西都可以做)。
但是本蒟蒻是用滚动数组水过了这道题。


本题有三个阶段:

  1. 对于5050%的数据 n100000n≤100000;保证UU操作不会撤销UU操作.
  2. 对于100100%的数据 n100000n≤100000UU操作可以撤销UU操作。
  3. IOIIOI挑战:必须使用在线算法完成该题。

阶段33就直接放弃了 毕竟我还不会主席树
那么对于阶段11,我们只要模拟堆,就可以很简单地得到这部分分。

var
  tail,n,i,j,x:longint;
  c:array[1..100000] of char;  //模拟堆
  ch,orz:char;
begin
  readln(n);
  for i:=1 to n do
   begin
     read(ch,orz);
     if ch='T' then  //插入
      begin
        inc(tail);  
        readln(c[tail]);  //放入堆顶
      end;
     if ch='Q' then  //询问
      begin
        readln(x);
        writeln(c[x]);  //输出第i位
      end;
     if ch='U' then  //删除
      begin
        readln(x);
        dec(tail,x)  //将最后x位输出
      end;
   end;
end.

对于阶段二,我们也要把它分为两部分。
我们可以开一个长度为100000100000ansistringansistring数组sss[i]s[i]表示第ii种情况。再开一个sumsum,表示第几种情况。这样,当我们遇到UU操作时,把前面xx个操作还原,其实就是不做前xx个操作,直接赋值为s[sum-x-1]。这样可以得到90分。
这里写图片描述

var
  sum,n,i,j,x:longint;
  s:array[1..100000] of ansistring;
  ch,orz:char;
begin
  readln(n);
  for i:=1 to n do
   begin
     read(ch,orz);
     if ch='T' then
      begin
        readln(ch);
        inc(sum);
        s[sum]:=s[sum-1]+ch;  //储存情况
      end;
     if ch='Q' then
      begin
        readln(x);
        writeln(s[sum][x]);  //输出现在的情况的第x位
      end;
     if ch='U' then
      begin
        readln(x);
        inc(sum);  //也算一种情况
        s[sum]:=s[sum-1-x];  //直接取第sum-1-x位
      end;
   end;
end.

但是这样会MLE,ss数组开的太大了。所以我们要用滚动数组来优化。每次将sumsum%2000020000就可以了。


代码:

const 
  k=20000;  //滚动数组,其他与90分代码一样。
var
  sum,n,i,j,x:longint;
  s:array[1..k] of ansistring;
  ch,orz:char;
begin
  readln(n);
  for i:=1 to n do
   begin
     read(ch,orz);
     if ch='T' then
      begin
        readln(ch);
        inc(sum);
        s[sum mod k]:=s[(sum-1)mod k]+ch;
      end;
     if ch='Q' then
      begin
        readln(x);
        writeln(s[sum mod k][x]);
      end;
     if ch='U' then
      begin
        readln(x);
        inc(sum);
        s[sum mod k]:=s[(sum-1-x) mod k];
      end;
   end;
end.
原文地址:https://www.cnblogs.com/hello-tomorrow/p/9313035.html