zoukankan      html  css  js  c++  java
  • BZOJ_1269_文本编辑器_[AHOI2006]_(Spaly)

    描述


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

    BZOJ_1507很像的题,多了一个反转操作,还是Splay简单区间操作的模板题.

    1269: [AHOI2006]文本编辑器editor

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 3223  Solved: 1203
    [Submit][Status][Discuss]

    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

    分析


    之前的操作和BZOJ_1507相同,多了一个反转操作:

    递归地将左右子树调换位置,为了节约时间,打上标记即可.

      1 #include <cstdio>
      2 #include <algorithm>
      3 using namespace std;
      4 
      5 const int maxn=(1<<21)+5;
      6 
      7 int n,at,cur,x;
      8 char str[maxn],s[10];
      9 
     10 struct Splay{
     11     struct node{
     12         node* ch[2],*pa;
     13         char v; int s; bool rev;
     14         node(char v,node* t):v(v){ ch[0]=ch[1]=pa=t; s=1; rev=false; }
     15         bool d() { return pa->ch[1]==this; }
     16         void setc(node* t,bool d) { ch[d]=t; t->pa=this; }
     17         void push_up() { s=ch[0]->s+ch[1]->s+1; }
     18         void push_down(){//向下传递反转
     19             if(rev){
     20                 node* c0=ch[0],* c1=ch[1];
     21                 setc(c1,0); setc(c0,1);//调换左右子树的位置(貌似可以直接用swap,但刚开始还是自己写吧)
     22                 ch[0]->rev^=true; ch[1]->rev^=true;
     23                 rev=false;
     24             }
     25         }
     26     }*root,*null;
     27     Splay(){
     28         null=new node('',NULL); null->s=0;
     29         root=new node('?',null);
     30         node* t=new node('!',null);
     31         root->setc(t,1);
     32         root->push_up();
     33     }
     34     void rot(node* o){
     35         node* pa=o->pa; bool d=o->d();
     36         pa->push_down(); o->push_down();//因为会改变o和pa,所以先把标记传递下去.
     37         pa->pa->setc(o,pa->d());
     38         pa->setc(o->ch[!d],d);
     39         o->setc(pa,!d);
     40         pa->push_up();
     41         if(pa==root) root=o;
     42     }
     43     void splay(node* o,node* pa){
     44         o->push_down();//如果需要转的话,在转的时候会向下传递,但如果不转的话,就在这里向下传递.
     45         while(o->pa!=pa){
     46             if(o->pa->pa==pa) rot(o);
     47             else o->d()==o->pa->d()?(rot(o->pa),rot(o)):(rot(o),rot(o));
     48         }
     49         o->push_up();
     50     }
     51     node* kth(int k){
     52         node* t=root; k++; 
     53         for(t->push_down();;t->push_down()){//每次顺便把标记传递下去.
     54             int s=t->ch[0]->s+1;
     55             if(s==k) return t;
     56             if(k>s) k-=s,t=t->ch[1];
     57             else t=t->ch[0];
     58         }
     59     }
     60     node* find(int l,int r){
     61         node* L=kth(l); splay(L,null);
     62         node* R=kth(r); splay(R,L);
     63         return R;
     64     }
     65     node* build(int l,int r){
     66         if(l==r) return new node(str[l],null);
     67         if(l>r) return null;
     68         int m=l+(r-l)/2;
     69         node* t=new node(str[m],null);
     70         t->setc(build(l,m-1),0);
     71         t->setc(build(m+1,r),1);
     72         t->push_up();
     73         return t;
     74     }
     75     void insert(int at,int cur){
     76         node* t=find(at,at+1);
     77         t->setc(build(0,cur),0); t->push_up();//因为在find函数中t是被splay过的,在splay中已经向下传递过标记了,所以这里不必再传递(remove函数中相同).
     78         splay(t,null);
     79     }
     80     void remove(int at,int n){
     81         node* t=find(at,at+n+1);
     82         t->setc(null,0); t->push_up();
     83         splay(t,null);
     84     }
     85     void setrev(int at,int n){//反转函数
     86         node* t=find(at,at+n+1);
     87         t->ch[0]->rev^=true;
     88         t->push_down();
     89     }
     90     void print(node* o){
     91         if(o==null) return;
     92         o->push_down();//先向下传递,不然会错.
     93         print(o->ch[0]);
     94         printf("%c",o->v);
     95         print(o->ch[1]);
     96     }
     97     void print(int at,int n){
     98         node* t=find(at,at+n+1);
     99         print(t->ch[0]);
    100         printf("
    ");
    101     }
    102 }tree;
    103 
    104 int main(){
    105     scanf("%d",&n);
    106     while(n--){
    107         scanf("%s",s);
    108         if(s[0]=='I'){
    109             scanf("%d",&x);
    110             cur=0;
    111             while(x--){
    112                 while(str[cur]=getchar(),str[cur]=='
    ');
    113                 cur++;
    114             }
    115             cur--;
    116             tree.insert(at,cur);
    117         }
    118         else if(s[0]=='M') scanf("%d",&at);
    119         else if(s[0]=='D'){
    120             scanf("%d",&x);
    121             tree.remove(at,x);
    122         }
    123         else if(s[0]=='G') tree.print(at,1);
    124         else if(s[0]=='R'){
    125             scanf("%d",&x);
    126             tree.setrev(at,x);
    127         }
    128         else if(s[0]=='P') at--;
    129         else at++;
    130     }
    131     return 0;
    132 }
    View Code
  • 相关阅读:
    BZOJ3732: Network(Kruskal重构树)
    AtCoder Beginner Contest 103
    2018.7.21NOIP模拟赛?解题报告
    PE刷题记
    杜教筛入门
    浅谈积性函数的线性筛法
    BZOJ4916: 神犇和蒟蒻(杜教筛)
    BZOJ2818: Gcd(莫比乌斯反演)
    LD1-B(最短路径-SPFA)
    UVa 10837 A Research Problem 欧拉函数
  • 原文地址:https://www.cnblogs.com/Sunnie69/p/5499765.html
Copyright © 2011-2022 走看看