Splay chapter 1 : NOI 2003 editor

学了Splay 发现这是一个很有意思的东西 至少可以很高效的做一些操作 特别是它的神操作splay 通过对一个节点和它的前驱和后继的各种脑补splay

我们可以把需要操作的部分全部转到一棵树上 所以 orz Tarjan ... 然后做了一些入门的题 这里记下NOI2003 的 editor:

Problem:

 

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 16
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
 
Solution:
        这个题据说是用什么块链可以做 当然我太弱了 捉不了 就把它当splay的练手题
         整个题中光标的位置我都用树根来表示了 这样似乎会便于操作 然后按惯例加Super_root 这里用了Byvoid牛的一个巧办法 再加了个虚根 然后把所有char后移一位
         对于Insert 我找它的后继结点 splay到root的rson 然后再其lson上加上字符(这里我把字符串建成了一棵树 好吧 其实是链)
         对于Delete 找到区间右端点+1 splay到root 然后删其左子树
         对于各种移动光标 直接search+splay
         然后是Get 据说递归中序会爆栈 那么我就一个一个输出了
         其中还有一些小细节 写的时候注意处理一下
 
Code:     
 
View Code
  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <iostream>
  6 #include <algorithm>
  7 #define rep(i,l,r) for(int i=l;i<=r;++i)
  8 using namespace std;
  9 int t,a,p = 1;
 10 char cmd[15],s[1024 * 1024 + 10];
 11 class Splay{
 12      private:
 13       struct Node{
 14            char ch;
 15            int size,cnt;
 16            Node *c[2],*fa;
 17            Node(char _ch,Node *_fa){
 18              ch = _ch; fa = _fa;
 19              cnt = 1; c[0] = c[1] = NULL;
 20            }
 21            int lsz() {return c[0] ? c[0]->size : 0;}
 22            int rsz() {return c[1] ? c[1]->size : 0;}
 23       };
 24       Node *root;
 25       inline void upd(Node *tag){
 26            if(!tag) return;
 27            tag->size = tag->cnt + tag->lsz() + tag->rsz();
 28       }
 29       inline void zig(Node *tag,int d){
 30            Node *f = tag->fa;
 31            int anti = 1 - d;
 32            f->c[d] = tag->c[anti];
 33            if(f->c[d]) 
 34             f->c[d]->fa = f;
 35            tag->fa = f->fa;
 36            if(tag->fa->c[0] == f)
 37               tag->fa->c[0] = tag;
 38            else
 39               tag->fa->c[1] = tag;
 40            f->fa = tag;
 41            tag->c[anti] = f;
 42            upd(f);
 43       }
 44       inline int f(Node *tag){
 45            return tag->fa->c[1] == tag;
 46       }
 47       inline void splay(Node *tag,Node *goal)
 48       {
 49            while(tag->fa != goal){
 50              if(tag->fa->fa == goal)
 51                 zig(tag,f(tag));
 52              else{
 53                 if(f(tag) == f(tag->fa))
 54                   zig(tag->fa,f(tag->fa)),zig(tag,f(tag));
 55                 else
 56                   zig(tag,f(tag)),zig(tag,f(tag));
 57              }
 58            }
 59            upd(tag);
 60       }
 61       inline Node *search(int key){
 62            Node *tag = root->c[0];
 63            while(tag && (key <= tag->lsz() || key > tag->lsz() + tag->cnt)){
 64               if(key > tag->lsz() + tag->cnt){
 65                 key -= tag->lsz() + tag->cnt; tag = tag->c[1];
 66               }else
 67                 tag = tag->c[0];
 68            }
 69            return tag;
 70       }
 71     public:
 72       Splay() { root = new Node('#',NULL); Node *tmp = new Node('^',root); root->c[0] = tmp; upd(tmp);}
 73       void insert(char *s){
 74            Node *chr = new Node(s[0],NULL),*tmp,*now,*tag = root->c[0];
 75            tmp = now = chr; chr->size = a;
 76            rep(i,1,a - 1)
 77            {
 78              now = new Node(s[i],tmp);
 79              tmp->c[1] = now; now->size = a - i;
 80              tmp = now;
 81            }
 82            Node *z = tag->c[1];
 83            while(z && z->c[0]) z = z->c[0];
 84            if(z){
 85               splay(z,tag);
 86               z->c[0] = chr; chr->fa = z;
 87               upd(z);
 88            }else{
 89               tag->c[1] = chr; chr->fa = tag;
 90               upd(tag);
 91             }
 92       }
 93       void trans(int x) {Node *tag = search(x); splay(tag,root);}
 94       void erase(int l){
 95            Node *tag = root->c[0];  if(!tag) return;
 96            Node *end = search(tag->lsz() + tag->cnt + l + 1);
 97            if(end){
 98             splay(end,tag); end->c[0] = NULL; upd(end);
 99            }else
100             tag->c[1] = NULL;
101            upd(tag);
102       }
103       void print(int l){
104            Node *tag = root->c[0];
105            rep(i,1,l){
106               Node *tmp = search(p + i);
107               splay(tmp,tag);
108               putchar(tmp->ch);
109            }
110            putchar('\n');
111       }
112 }tree;
113 int main()
114 {
115     freopen("input.in","r",stdin); freopen("output.out","w",stdout);
116     scanf("%d",&t); 
117     rep(i,1,t)
118     {
119       scanf("%s %d",cmd,&a);
120       if(cmd[0] == 'I'){
121         char c;
122         for (int i=0;i<a;)
123         {
124             while ((c=getchar())==10 || c==13);
125             s[i ++]=c;
126         }
127         tree.insert(s); continue;
128       }
129       if(cmd[0] == 'M'){
130         tree.trans(a + 1); p = a + 1; continue;
131       }
132       if(cmd[0] == 'D'){
133         tree.erase(a); continue;
134       }
135       if(cmd[0] == 'G'){
136         tree.print(a); continue;
137       }
138       if(cmd[0] == 'P'){
139         tree.trans(-- p); continue;
140       }
141       if(cmd[0] == 'N'){
142         tree.trans(++ p); continue;
143       }
144     }
145     return 0;
146 }

 

然后 就没有然后了

 

转载于:https://www.cnblogs.com/nardy/archive/2012/12/10/2811934.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值