BZOJ_1507_Editor_[NOI2003]_(Splay)

描述


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

简单区间操作的模板题

 

 

1507: [NOI2003]Editor

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 3092  Solved: 1244
[Submit][Status][Discuss]

 

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

 

分析


和BZOJ_1269很像,而且更简单.

首先加入一个起始字符和尾字符(因为我们解决问题的办法都是在两个区间之间进行的).

操作:

1.插入:把at转到根节点,把at+1转到根节点的右儿子,然后在at+1的左儿子处插入即可.

2.移动:直接输入到at即可.

3.删除:把at转到根节点,把at+n+1转到根节点的右儿子,然后把at+n+1的左儿子直接改成null即可.

4.&5.移动光标就at--,at++即可.

 

  1 #include <cstdio>
  2 #include <algorithm>
  3 using namespace std;
  4  
  5 const int maxn=(2<<21)+5,oo=~0u>>1;
  6  
  7 int n,x,at,cur;
  8 char str[maxn],s[10];
  9  
 10 struct Splay{
 11     struct node{
 12         node* ch[2],* pa;
 13         char v; int s;
 14         node(int v,node* t):v(v){ ch[0]=ch[1]=pa=t; s=1; }
 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     }*root,*null;
 19     Splay(){
 20         null=new node('\0',NULL); null->s=0;
 21         root=new node('\0',null);
 22         node* t=new node('\0',null);
 23         root->setc(t,1);
 24         root->push_up();
 25     }
 26     void rot(node* o){
 27         node* pa=o->pa; bool d=o->d();
 28         pa->pa->setc(o,pa->d());
 29         pa->setc(o->ch[!d],d);
 30         o->setc(pa,!d);
 31         pa->push_up();
 32         if(pa==root) root=o;
 33     }
 34     void splay(node* o,node* pa){
 35         while(o->pa!=pa){
 36             if(o->pa->pa==pa) rot(o);
 37             else o->d()==o->pa->d()?(rot(o->pa),rot(o)):(rot(o),rot(o));
 38         }
 39         o->push_up();
 40     }
 41     node* kth(int k){
 42         k++;
 43         for(node* t=root;;){
 44             int s=t->ch[0]->s+1;
 45             if(s==k) return t;
 46             if(k>s) k-=s,t=t->ch[1];
 47             else t=t->ch[0];
 48         }
 49     }
 50     node* build(int l,int r){
 51         if(l==r) return new node(str[l],null);
 52         if(l>r) return null;
 53         int m=l+(r-l)/2;
 54         node* t=new node(str[m],null);
 55         t->setc(build(l,m-1),0);
 56         t->setc(build(m+1,r),1);
 57         t->push_up();
 58         return t;
 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     void insert(int at,int cur){
 66         node* t=find(at,at+1);
 67         t->setc(build(0,cur),0); t->push_up();
 68         splay(t,null);
 69     }
 70     void remove(int at,int n){
 71         node* t=find(at,at+n+1);
 72         t->setc(null,0); t->push_up();
 73         splay(t,null);
 74     }
 75     void print(node* o){
 76         if(o==null) return;
 77         print(o->ch[0]);
 78         printf("%c",o->v);
 79         print(o->ch[1]);
 80     }
 81     void print(int at,int n){
 82         node* t=find(at,at+n+1);
 83         print(t->ch[0]);
 84         printf("\n");
 85     }
 86 }tree;
 87  
 88 int main(){
 89     scanf("%d",&n);
 90     while(n--){
 91         scanf("%s",s);
 92         if(s[0]=='I'){
 93             cur=0;
 94             scanf("%d",&x);
 95             while(x--){
 96                 while(str[cur]=getchar(),str[cur]=='\n');
 97                 cur++;
 98             }
 99             cur--;
100             tree.insert(at,cur);
101         }
102         else if(s[0]=='M') scanf("%d",&at);
103         else if(s[0]=='D'){
104             scanf("%d",&x);
105             tree.remove(at,x);
106         }
107         else if(s[0]=='G'){
108             scanf("%d",&x);
109             tree.print(at,x);
110         }
111         else if(s[0]=='P') at--;
112         else at++;
113     }
114     return 0;
115 }
View Code

 

 

 

 


 

posted @ 2016-05-16 21:59  晴歌。  阅读(187)  评论(0编辑  收藏  举报