zoukankan      html  css  js  c++  java
  • [AHOI2006]Editor文本编辑器Splay Pascal

    http://www.lydsy.com/JudgeOnline/problem.php?id=1269

    1269: [AHOI2006]文本编辑器editor
    Time Limit: 10 Sec  Memory Limit: 162 MB

    Description
    这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器。你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:   文本:由0个或多个字符构成的序列。这些字符的ASCII码在闭区间[32, 126]内,也就是说,这些字符均为可见字符或空格。光标:在一段文本中用于指示位置的标记,可以位于文本的第一个字符之前,文本的最后一个字符之后或文本的某两个相邻字符之间。文本编辑器:为一个可以对一段文本和该文本中的一个光标进行如下七条操作的程序。如果这段文本为空,我们就说这个文本编辑器是空的。 编写一个程序: 建立一个空的文本编辑器。 从输入文件中读入一些操作指令并执行。 对所有执行过的GET操作,将指定的内容写入输出文件。

    Input
    输入文件中第一行是指令条数N,以下是需要执行的N个操作。除了回车符之外,输入文件的所有字符的ASCII码都在闭区间[32, 126]内。且行尾没有空格。

    Output
    依次对应输入文件中每条GET指令的输出,不得有任何多余的字符。

    Sample Input
    10
    Insert 13
    Balanced eert
    Move 2
    Delete 5
    Next
    Insert 7
    editor
    Move 0
    Get
    Move 11
    Rotate 4
    Get

    Sample Output
    B
    t


    HINT

    对输入数据我们有如下假定: MOVE操作不超过50 000个,INSERT、DELETE和ROTATE操作作的总个数不超过6 000,GET操作不超过20 000个,PREV和NEXT操作的总个数不超过20 000。 所有INSERT插入的字符数之和不超过2M(1M=1 024*1 024)。 DELETE操作、ROTATE操作和GET操作执行时光标后必然有足够的字符。MOVE、PREV、NEXT操作不会把光标移动到非法位置。 输入文件没有错误。


    Source
    鸣谢seter重新制作数据

     裸Splay。有几个问题导致调了很长时间……

    1、update旋转标记时千万不要忘记清空自身标记,同时子树的标记应该取反,而非直接赋false

    2、update最好过程内直接操作本身、左右子树,这样不容易写错。

    3、pushup时一定要记得更新其父亲各节点!

    program editor;
     //Splay Tree
     //By HT 2012/12
     //BZOJ P1269
     //AHOI2004 Editor
     
     {$DEFINE INDEBUG}
     
     Type
      node=longint;
      rec=record
        lch,rch,f,s:longint;
        w:char;
        ro:boolean;
      end;
      
     Var
      q:array[0..2000000] of rec;
      ss:array[0..10000] of char;
      h,null,now:node;
      top,i,j,k,n:longint;
      c:char;
      
     Procedure fopen;
       begin
       assign(input,'editor.in');
       assign(output,'editor.out');
       reset(input);
       rewrite(output);
     end;
     
     Procedure fclose;
       begin
       close(input);
       close(output);
     end;
     
     Function mmin(a,b:longint):longint;
       begin
       if a<b then exit(a) else exit(b);
     end;
     
     Procedure new(var p:node);
       begin
       inc(top);
       p:=top;
     end;
     
     Procedure pushup(P:node);
       begin
       while p<>null do
         begin
         q[p].s:=q[q[p].lch].s+q[q[p].rch].s+1;
         p:=q[p].f;
       end;
     end;
     
     Procedure oldupdate(P:node);
     var
      y:node;
       begin
       if p=null then exit;
       if q[p].ro then
         begin
         y:=q[p].lch;
         q[p].lch:=q[p].rch;
         q[p].rch:=y;
         if q[p].lch<>null then q[q[p].lch].ro:=not q[q[p].lch].ro;
         if q[p].rch<>null then q[q[p].rch].ro:=not q[q[p].rch].ro;
         q[p].ro:=false;
       end;
     end;
     
     Procedure update(P:node);
       begin
       oldupdate(q[p].lch);
       oldupdate(q[p].rch);
       oldupdate(p);
     
     
     end;
     
     Procedure zig(P:node);// LeftRonate
     var
      newroot:node;
       begin
       if p=null then exit;
       update(p);
       if q[p].rch=null then exit;
       newroot:=q[p].rch;
       q[newroot].f:=q[p].f;
       if q[p].f<>null then
         if q[q[p].f].lch=p then
           q[q[p].f].lch:=newroot else
           q[q[p].f].rch:=newroot
         else
         h:=newroot;
       q[p].rch:=q[newroot].lch;
       if q[p].rch<>null then
         q[q[p].rch].f:=p;
       q[newroot].lch:=p;
       q[p].f:=newroot;
       pushup(p);
       pushup(newroot);
     end;
     
     Procedure zag(P:node);//RightRonate
     var
      newroot:node;
       begin
       
       if p=null then exit;
       update(p);
       if q[p].lch=null then exit;
       
       newroot:=q[p].lch;
       q[newroot].f:=q[p].f;
       if q[p].f<>null then
         if q[q[p].f].lch=p then
           q[q[p].f].lch:=newroot else
           q[q[p].f].rch:=newroot
         else
         h:=newroot;
       q[p].lch:=q[newroot].rch;
       if q[p].lch<>null then
         q[q[p].lch].f:=p;
       q[newroot].rch:=p;
       q[p].f:=newroot;
       pushup(p);
       pushup(newroot);
     end;
     
     Procedure Splay(P,tar:node);
     var
      x,y,z:node;
       begin
       if p=null then exit;
       x:=p;
       while q[x].f<>tar do
         begin
         y:=q[x].f;
         z:=q[y].f;
         update(z);
         update(y);
         update(x);
         if z=tar then
           begin
           if q[y].lch=x then zag(y) else zig(y);
           exit;
         end;
         if (q[z].lch=y) and (q[y].lch=x) then
           begin
           zag(z);
           zag(y);
         end else
         if (q[z].rch=y) and (q[y].rch=x) then
           begin
           zig(z);
           zig(y);
         end else
         if (q[z].lch=y) and (q[y].rch=x) then
           begin
           zig(y);
           zag(z);
         end else
           begin
           zag(y);
           zig(z);
         end;
       end;
     end;
     
     Function kth(P:longint):node;
       begin
       kth:=h;
       update(kth);
       if p>q[h].s then p:=q[h].s;
       while q[kth].s>1 do
         begin
         if q[q[kth].lch].s+1=p then exit;
         if p<q[q[kth].lch].s+1 then kth:=q[kth].lch else
           begin
           dec(p,q[q[kth].lch].s+1);
           kth:=q[kth].rch;
         end;
         update(kth);
       end;
     end;
     
     Function buildtree(pl,pr:longint):node;
     var
      mid:longint;
      ans:node;
       begin
       if pr<pl then exit(null);
       if pl=pr then
          begin
          new(ans);
          with q[ans] do
            begin
            s:=1;
            w:=ss[pl];
            lch:=null;
            rch:=null;
            f:=null;
            ro:=false;
          end;
          exit(ans);
        end;
        mid:=(pl+pr) div 2;
        new(ans);
        with q[ans] do
          begin
          s:=pr-pl+1;
          w:=ss[mid];
          ro:=false;
          lch:=buildtree(pl,mid-1);
          rch:=buildtree(mid+1,pr);
          if lch<>null then
            q[lch].f:=ans;
          if rch<>null then
            q[rch].f:=ans;
          exit(ans);
        end;
          
     end;
     
     Procedure Insert(k:longint);
     var
      p:node;
       begin
       p:=now;
       update(p);
       if q[p].rch=null then 
         begin
         q[p].rch:=buildtree(1,k);
         q[q[p].rch].f:=p;
         pushup(p);
         exit;
       end;
       p:=q[p].rch;
       update(p);
       while q[p].lch<>null do
         begin
         p:=q[p].lch;
         update(p);
       end;
       q[p].lch:=buildtree(1,k);
       q[q[p].lch].f:=p;
       pushup(p);
     end;
     
     Procedure move(P:longint);
       begin
       now:=h;
       update(now);
       while q[now].s>1 do
         begin
         if q[q[now].lch].s+1=p then exit;
         if p<q[q[now].lch].s+1 then 
           now:=q[now].lch
         else
           begin
           dec(p,q[q[now].lch].s+1);
           now:=q[now].rch;
         end;
         update(now);
       end;
     end;
     
     Procedure next;
     var
      o:node;
       begin
       update(now);
       if q[now].rch<>null then
         begin
         now:=q[now].rch;
         update(now);
         while q[now].lch<>null do
           begin
           now:=q[now].lch;
           update(now);
         end;
       end else
         begin
         o:=q[now].f;
         update(o);
         while o<>null do
           begin
           if q[o].lch=now then break;
           o:=q[o].f;
           now:=q[now].f;
           update(o);
         end;
         now:=o;
       end;
       splay(now,null);
     end;
     
     Procedure prev;
     var
      o:node;
       begin
       update(now);
       if q[now].lch<>null then
         begin
         now:=q[now].lch;
         update(now);
         while q[now].rch<>null do
           begin
           now:=q[now].rch;
           update(now);
         end;
       end else
         begin
         o:=q[now].f;
         update(o);
         while o<>null do
           begin
           if q[o].rch=now then break;
           o:=q[o].f;
           now:=q[now].f;
           update(o);
         end;
         now:=o;
       end;
       splay(now,null);
     end;
     
     Function Getpos:longint;
     var
      p,qq:node;
       begin
       p:=q[now].f;
       qq:=now;
       getpos:=q[q[now].lch].s+1;
      // if now=null then error(renone);
       update(p);
       update(qq);
       while p<>null do
         begin
         if q[p].rch=qq then inc(getpos,q[q[p].lch].s+1);
         p:=q[p].f;
         qq:=q[qq].f;
         update(p);
         update(qq);
       end;
     end;
     
     Procedure get;
     var
      oldnow:node;
       begin
       oldnow:=now;
       if q[h].s<>getpos then
         begin
         next;
         writeln(q[now].w);
       end
     
           else writeln(' ');
     
       now:=oldnow;
       splay(now,null);
     end;
     
     Procedure delete(P:longint);
     var
      tmp:node;
       begin
       tmp:=kth(mmin(q[h].s,getpos+p+1));
       splay(now,null);
       splay(tmp,h);
       update(h);
       update(q[h].rch);
       update(q[h].lch);
       q[q[h].rch].lch:=null;
       pushup(q[h].rch);
     end;
     
     Procedure ronate(P:longint);
     var
      tmp:node;
       begin
       tmp:=kth(mmin(q[h].s,getpos+p+1));
       splay(now,null);
       splay(tmp,h);
     
       update(q[q[h].rch].lch);
       update(q[h].rch);
       update(h);
       q[q[q[h].rch].lch].ro:=true;
       //q[q[h].rch].lch:=null;
     end;
     
     Procedure init;
     var
      p:node;
       begin
       top:=0;
       new(null);
       with q[null] do
         begin
         s:=0;
         lch:=null;
         rch:=null;
         f:=null;
         w:=#0;
       end;
       new(h);now:=h;
       with q[h] do
         begin
         lch:=null;
         rch:=null;
         f:=null;
         w:=#0;
         s:=1;
       end;
       for i:=1 to 10 do
         ss[i]:=#0;
       insert(10);
     end;
     
     Procedure readchar(P:longint);
     var
      i:longint;
      o:char;
       begin
       for i:=1 to p do
         read(o);
     end;
     
       begin
       {$IFDEF INDEBUG}
       fopen;
       {$ENDIF}
       readln(n);
       init;
       for i:=1 to n do
         begin
         read(c);
         case c of
           'M':
             begin
             readchar(3);
             readln(k);
             move(k+1);
           end;
           'I':
             begin
             readchar(5);
             readln(k);
             for j:=1 to k do
               read(ss[j]);
             readln;
             insert(k);
           end;
           'D':
             begin
             readchar(5);
             readln(k);
             delete(k);
           end;
           'R':
             begin
             readchar(5);
             readln(k);
             ronate(k);
           end;
           'G':
             begin
             get;
             readchar(2);
             readln;
           end;
           'P':
             begin
             prev;
             readchar(3);
             readln;
           end;
           'N':
             begin
             next;
             readchar(3);
             readln;
           end;
         end;
      // writeln('No.',i,' Succeed! ');
       //flush(output);
       //get;
       end;
       {$IFDEF INDEBUG}
       fclose;
       {$ENDIF}
     end.
    
  • 相关阅读:
    spring Bean的完整生命周期
    idea+maven+ssm搭建boot_crm项目遇到的问题
    面试题:死锁的四个必要条件
    面试题:静态代理和动态代理的区别和联系 没用
    面试题: Struts2
    我所总结的设计模式 合应用场景
    hibernate 对象OID
    hibernate第三天 一对多 , 多对多
    hibernate里的实体类中不能重写toString
    存储前set方法相互关联 只关联了一方 分别set
  • 原文地址:https://www.cnblogs.com/htfy/p/2833107.html
Copyright © 2011-2022 走看看