zoukankan      html  css  js  c++  java
  • BZOJ 1269: [AHOI2006]文本编辑器editor (splay tree)

    1269: [AHOI2006]文本编辑器editor

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1213  Solved: 454
    [Submit][Status]

    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

      1 /* ***********************************************
      2 Author        :kuangbin
      3 Created Time  :2013/8/26 22:47:15
      4 File Name     :F:2013ACM练习专题学习splay_tree_2文本编辑器editor.cpp
      5 ************************************************ */
      6 
      7 #include <stdio.h>
      8 #include <string.h>
      9 #include <iostream>
     10 #include <algorithm>
     11 #include <vector>
     12 #include <queue>
     13 #include <set>
     14 #include <map>
     15 #include <string>
     16 #include <math.h>
     17 #include <stdlib.h>
     18 #include <time.h>
     19 using namespace std;
     20 
     21 /*
     22  * 对字符串进行插入、删除、反转、查询第k个字符等操作
     23  * Move k : 将光标移到到第k个字符之后
     24  * Insert n S : 在光标后插入长度为n的字符串S,光标位置不变
     25  * Delete n :删除光标后的n个字符,光标位置保持不变
     26  * Rotate n :反转光标后的n个字符,光标位置不变
     27  * Get      :输出光标后的一个字符
     28  * Prev     :光标前移一个字符
     29  * Next     :光标后移一个字符
     30  *
     31  *
     32  *用一个变量记录光标位置,对于Move,Prev,Next 直接改变这个变量
     33  *
     34  */
     35 #define Key_value ch[ch[root][1]][0]
     36 const int MAXN = 2*1024*1024+10;
     37 int ch[MAXN][2],pre[MAXN],rev[MAXN],size[MAXN];
     38 int root,tot1;
     39 char key[MAXN];
     40 int s[MAXN],tot2;
     41 
     42 int pos;//光标位置
     43 char str[MAXN];//需要插入的字符串
     44 void NewNode(int &r,int father,char k)
     45 {
     46     if(tot2) r = s[tot2--];
     47     else r = ++tot1;
     48     ch[r][0] = ch[r][1] = 0;
     49     pre[r] = father;
     50     rev[r] = 0;
     51     key[r] = k;
     52     size[r] = 1;
     53 }
     54 void Update_Rev(int r)
     55 {
     56     if(!r)return;
     57     swap(ch[r][0],ch[r][1]);
     58     rev[r] ^= 1;
     59 }
     60 void push_up(int r)
     61 {
     62     size[r] = size[ch[r][0]] + size[ch[r][1]] + 1;
     63 }
     64 void push_down(int r)
     65 {
     66     if(rev[r])
     67     {
     68         Update_Rev(ch[r][0]);
     69         Update_Rev(ch[r][1]);
     70         rev[r] = 0;
     71     }
     72 }
     73 void Build(int &x,int l,int r,int father)
     74 {
     75     if(l > r)return;
     76     int mid = (l+r)/2;
     77     NewNode(x,father,str[mid]);
     78     Build(ch[x][0],l,mid-1,x);
     79     Build(ch[x][1],mid+1,r,x);
     80     push_up(x);
     81 }
     82 void Init()
     83 {
     84     pos = 0;
     85     root = tot1 = tot2 = 0;
     86     ch[root][0] = ch[root][1] = pre[root] = size[root] = rev[root] = 0;
     87     NewNode(root,0,' ');
     88     NewNode(ch[root][1],root,' ');
     89     push_up(ch[root][1]);
     90     push_up(root);
     91 }
     92 void Rotate(int x,int kind)
     93 {
     94     int y = pre[x];
     95     push_down(y);
     96     push_down(x);
     97     ch[y][!kind] = ch[x][kind];
     98     pre[ch[x][kind]] = y;
     99     if(pre[y])
    100         ch[pre[y]][ch[pre[y]][1]==y] = x;
    101     pre[x] = pre[y];
    102     ch[x][kind] = y;
    103     pre[y] = x;
    104     push_up(y);
    105 }
    106 void Splay(int r,int goal)
    107 {
    108     push_down(r);
    109     while(pre[r] != goal)
    110     {
    111         if(pre[pre[r]] == goal)
    112         {
    113             push_down(pre[r]);
    114             push_down(r);
    115             Rotate(r,ch[pre[r]][0]==r);
    116         }
    117         else
    118         {
    119             push_down(pre[pre[r]]);
    120             push_down(pre[r]);
    121             push_down(r);
    122             int y = pre[r];
    123             int kind = ch[pre[y]][0]==y;
    124             if(ch[y][kind] == r)
    125             {
    126                 Rotate(r,!kind);
    127                 Rotate(r,kind);
    128             }
    129             else
    130             {
    131                 Rotate(y,kind);
    132                 Rotate(r,kind);
    133             }
    134         }
    135     }
    136     push_up(r);
    137     if(goal == 0)root = r;
    138 }
    139 int Get_kth(int r,int k)
    140 {
    141     push_down(r);
    142     int t = size[ch[r][0]] + 1;
    143     if(t == k)return r;
    144     if(t > k)return Get_kth(ch[r][0],k);
    145     else return Get_kth(ch[r][1],k-t);
    146 }
    147 //在光标后插入长度为len的字符串
    148 void INSERT(int len)
    149 {
    150     Splay(Get_kth(root,pos+1),0);
    151     Splay(Get_kth(root,pos+2),root);
    152     Build(Key_value,0,len-1,ch[root][1]);
    153     push_up(ch[root][1]);
    154     push_up(root);
    155 }
    156 void erase(int r)
    157 {
    158     if(r)
    159     {
    160         s[++tot2] = r;
    161         erase(ch[r][0]);
    162         erase(ch[r][1]);
    163     }
    164 }
    165 void DELETE(int len)
    166 {
    167     Splay(Get_kth(root,pos+1),0);
    168     Splay(Get_kth(root,pos+len+2),root);
    169     erase(Key_value);
    170     pre[Key_value] = 0;
    171     Key_value = 0;
    172     push_up(ch[root][1]);
    173     push_up(root);
    174 }
    175 void Reverse(int len)
    176 {
    177     Splay(Get_kth(root,pos+1),0);
    178     Splay(Get_kth(root,pos+len+2),root);
    179     Update_Rev(Key_value);
    180     push_up(ch[root][1]);
    181     push_up(root);
    182 }
    183 
    184 int main()
    185 {
    186      //freopen("in.txt","r",stdin);
    187     //freopen("out.txt","w",stdout);
    188     int n;
    189     int x;
    190     char op[20];
    191     while(scanf("%d",&n) == 1)
    192     {
    193         Init();
    194         while(n--)
    195         {
    196             scanf("%s",&op);
    197             if(op[0] == 'M')
    198             {
    199                 scanf("%d",&x);
    200                 pos = x;
    201             }
    202             else if(op[0] == 'P')pos--;
    203             else if(op[0] == 'N')pos++;
    204             else if(op[0] == 'I')
    205             {
    206                 scanf("%d%*c",&x);
    207                 gets(str);
    208                 INSERT(x);
    209             }
    210             else if(op[0] == 'D')
    211             {
    212                 scanf("%d",&x);
    213                 DELETE(x);
    214             }
    215             else if(op[0] == 'R')
    216             {
    217                 scanf("%d",&x);
    218                 Reverse(x);
    219             }
    220             else if(op[0] == 'G')
    221             {
    222                 printf("%c
    ",key[Get_kth(root,pos+2)]);
    223             }
    224         }
    225     }
    226 
    227     return 0;
    228 }
  • 相关阅读:
    java生成json字符串的方法
    JSON的三种解析方式
    Android Studio你不知道的调试技巧
    Android 打开URL
    build.gradle中引入jar
    Spark RDD/Core 编程 API入门系列之map、filter、textFile、cache、对Job输出结果进行升和降序、union、groupByKey、join、reduce、lookup(一)
    NovaMind *的安装、和谐破解到永久使用
    小Q书桌的下载、安装和使用
    作业提交过程分析(源码)
    SparkContext的初始化过程分析(源码)
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3284085.html
Copyright © 2011-2022 走看看