[BZOJ1507] [NOI2003] Editor (splay)

Description

Input

  输入文件editor.in的第一行是指令条数t,以下是需要执行的t个操作。其中: 为了使输入文件便于阅读,Insert操作的字符串中可能会插入一些回车符,请忽略掉它们(如果难以理解这句话,可以参考样例)。 除了回车符之外,输入文件的所有字符的ASCII码都在闭区间[32, 126]内。且行尾没有空格。
  这里我们有如下假定:
   MOVE操作不超过50000个,INSERT和DELETE操作的总个数不超过4000,PREV和NEXT操作的总个数不超过200000。
   所有INSERT插入的字符数之和不超过2M(1M=1024*1024),正确的输出文件长度不超过3M字节。
   DELETE操作和GET操作执行时光标后必然有足够的字符。MOVE、PREV、NEXT操作必然不会试图把光标移动到非法位置。
   输入文件没有错误。 对C++选手的提示:经测试,最大的测试数据使用fstream进行输入有可能会比使用stdio慢约1秒。

Output

  输出文件editor.out的每行依次对应输入文件中每条GET指令的输出。

Sample Input

15
Insert 26
abcdefghijklmnop
qrstuv wxy
Move 15
Delete 11
Move 5
Insert 1
^
Next
Insert 1
_
Next
Next
Insert 4
.\/.
Get 4
Prev
Insert 1
^
Move 0
Get 22

Sample Output

.\/.
abcde^_^f.\/.ghijklmno

HINT 

Source

Solution

  splay的区间操作。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 struct spaly
  4 {
  5     char key;
  6     int siz, fa, c[2];
  7 }a[2100005];
  8 char inss[2100005];
  9 int ptot;
 10  
 11 void push_up(int k)
 12 {
 13     a[k].siz = a[a[k].c[0]].siz + a[a[k].c[1]].siz + 1;
 14 }
 15  
 16 void rotate(int &k, int x)
 17 {
 18     int y = a[x].fa, z = a[y].fa;
 19     int dy = a[y].c[1] == x, dz = a[z].c[1] == y;
 20     if(k == y) k = x, a[x].fa = z;
 21     else a[z].c[dz] = x, a[x].fa = z;
 22     a[y].c[dy] = a[x].c[!dy], a[a[x].c[!dy]].fa = y;
 23     a[x].c[!dy] = y, a[y].fa = x;
 24     push_up(y);
 25 }
 26  
 27 void splay(int &k, int x)
 28 {
 29     while(k != x)
 30     {
 31         int y = a[x].fa, z = a[y].fa;
 32         if(k != y)
 33             if(a[y].c[1] == x ^ a[z].c[1] == y) rotate(k, x);
 34             else rotate(k, y);
 35         rotate(k, x);
 36     }
 37     push_up(x);
 38 }
 39  
 40 int find(int k, int x)
 41 {
 42     if(!k || x == a[a[k].c[0]].siz + 1) return k;
 43     if(x <= a[a[k].c[0]].siz) return find(a[k].c[0], x);
 44     return find(a[k].c[1], x - a[a[k].c[0]].siz - 1);
 45 }
 46  
 47 void build(int &k, int fa, int i, int m)
 48 {
 49     if(i == m) return;
 50     k = ++ptot, a[k].fa = fa, a[k].key = inss[i];
 51     build(a[k].c[1], k, i + 1, m);
 52     push_up(k);
 53 }
 54  
 55 void printf(int k)
 56 {
 57     if(!k) return;
 58     printf(a[k].c[0]), printf("%c", a[k].key), printf(a[k].c[1]);
 59 }
 60  
 61 int main()
 62 {
 63     int n, m, root = 1, pos = 0, ctot = 0;
 64     char op[10];
 65     scanf("%d", &n), ptot = 2;
 66     a[1].c[1] = 2, a[1].siz = 2, a[2].siz = 1, a[2].fa = 1;
 67     while(n--)
 68     {
 69         scanf("%s", op);
 70         if(op[0] == 'M') scanf("%d", &pos);
 71         if(op[0] == 'I')
 72         {
 73             scanf("%d", &m), ctot += m;
 74             for(int i = 0; i < m; i++)
 75             {
 76                 inss[i] = getchar();
 77                 if(inss[i] < 32 || inss[i] > 126) i--;
 78             }
 79             splay(root, find(root, pos + 1));
 80             splay(a[root].c[1], find(root, pos + 2));
 81             build(a[a[root].c[1]].c[0], a[root].c[1], 0, m);
 82             push_up(a[root].c[1]), push_up(root);
 83         }
 84         if(op[0] == 'D')
 85         {
 86             scanf("%d", &m), m = min(m, ctot - pos);
 87             splay(root, find(root, pos + 1));
 88             splay(a[root].c[1], find(root, pos + m + 2));
 89             a[a[root].c[1]].c[0] = 0, ctot -= m;
 90             push_up(a[root].c[1]), push_up(root);
 91         }
 92         if(op[0] == 'G')
 93         {
 94             scanf("%d", &m), m = min(m, ctot - pos);
 95             splay(root, find(root, pos + 1));
 96             splay(a[root].c[1], find(root, pos + m + 2));
 97             printf(a[a[root].c[1]].c[0]), puts("");
 98         }
 99         if(op[0] == 'P') pos--;
100         if(op[0] == 'N') pos++;
101     }
102     return 0;
103 }
View Code

 

posted @ 2016-04-05 20:24  CtrlCV  阅读(213)  评论(0编辑  收藏  举报