BZOI 1507 [NOI2003] Editor

Background

After trying to solve problem EDIT1(Editor) and being ****ed by Brainf**k, Blue Mary decided to set another difficult problem about editor.

Description

Some definations:

  • Text: It‘s a sequence that consists characters whose ASCII code is in [32,126].
  • Cursor: It‘s a sign for pointing out the current position.It can be at the start or the end of the text or between two consecutive characters of the text.

Editor is a structure.It contains one text and one cursor.The operations are listed below:

--------------------------------------------------------------------------
| Name        | Input format |              function                     |
--------------------------------------------------------------------------
| Move(k)     | Move k       | Move the cursor after the kth character   |
|             |              | in the text. If k=0, you should put       |
|             |              | the cursor at the start of the text.      |
--------------------------------------------------------------------------
| Insert(n,s) | Insert n s   | Insert string s whose length is n(>=1)    |
|             |              | after the cursor.The cursor doesn‘t move. |
--------------------------------------------------------------------------
| Delete(n)   | Delete n     | Delete n(>=1) characters after the cursor.|
|             |              | The cursor doesn‘t move.                  |
--------------------------------------------------------------------------
| Get(n)      | Get n        | Output n(>=1) characters after the cursor.|
--------------------------------------------------------------------------
| Prev()      | Prev         |  Move the cursor one character forward.   |
--------------------------------------------------------------------------
| Next()      | Next         |  Move the cursor one character backward.  |
--------------------------------------------------------------------------

If the text of a editor is empty,we say the editor is empty.

Here is an example._ denotes to the cursor,$ denotes to the start and the end.At start the editor is empty.

------------------------------------------------------------------------------
|         Operation          |  Text after the operation |        Output     |
------------------------------------------------------------------------------
| INSERT(13,"Balanced tree") |  $_Balanced tree$         | $$                |
------------------------------------------------------------------------------
| MOVE(2)                    |  $Ba_lanced tree$         | $$                |
------------------------------------------------------------------------------
| DELETE(5)                  |  $Ba_d tree$              | $$                |
------------------------------------------------------------------------------
| NEXT()                     |  $Bad_ tree$              | $$                |
------------------------------------------------------------------------------
| INSERT(7," editor")        |  $Bad_ editor tree$       | $$                |
------------------------------------------------------------------------------
| MOVE(0)                    |  $_Bad editor tree$       | $$                |
------------------------------------------------------------------------------
| GET(15)                    |  $_Bad editor tree$       | $Bad editor tree$ |
------------------------------------------------------------------------------

Your task is:

  • Build an empty editor.
  • Read some operations from the standard input and operate them.
  • For each Get operation, write the answer to the output.

Input

the very first line contains the number of testcases T(T<=4).T tests follow.

For each test, the first line is the number of operations N.N operations follow.

Blue Mary is so depressed with the problem EDIT1 that she decides to make the problem more difficult.So she inserts many extra line breaks in the string of the Insert operation.You must ignore them.

Except line breaks, all the charaters‘ ASCII code are in [32,126]. There‘s no extra space at the end of a line.

You can assume that for each test case:

  • No invalid operation is in the input.
  • Number of move operations is no more than 50000.
  • Number of the total of insert and delete operations is no more than 4000.
  • Number of the total of prev and next operations is no more than 200000.
  • The characters inserted will not more than 2MB.The valid output will not more than 3MB.

Output

The output should contain T blocks corresponding to each testcase.

For each test case, the output should contain as many lines as the get operations in the input.Each line should contains the output of each get operation.

Example

Input: 1
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 Output:
.\/.
abcde^_^f.\/.ghijklmno

Warning: large Input/Output data, be careful with certain languages

Blue Mary‘s note: the test case #1 has something wrong and it has been fixed on April 27th, 2007.Solutions has been rejudged. Please accept my apology.

题目取自SPOJ

几点注意的:

1、bzoj样例有误。

2、Insert操作如果读入长度用scanf("%d\n",&x)读,会自动过滤下一行空格,导致Wa90.

相信这是我写过最差的程序了。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstdlib>
using namespace std;
#define MAXN MAXT
#define MAXT 1024*1024*4+1000
int n,m;
struct Splay_tree
{
        struct node
        {
                node *ch[2],*fa;
                char w;
                int siz;
        };
        node E[MAXN],nil_node;
        queue<node* > Q;
        node *root,*nil;
        Splay_tree()
        {
                int i;
                for (i=1;i<MAXT;i++)
                {
                        Q.push(&E[i]);
                }
                nil_node.ch[0]=nil_node.ch[1]=NULL;
                nil_node.w=‘#‘;
                nil_node.siz=0;
                nil=&nil_node;
                root=nil;
                root->fa=nil;
        }
        void update(node *now)
        {
                if (now==nil)throw "illegal update";
                now->siz=now->ch[0]->siz+now->ch[1]->siz+1;
        }
        void rotate(node *now,int p)//注意不要改变nil的值,now的祖父节点或儿子节点可能为nil
        {
                node *pnt=now->fa;
                now->fa=pnt->fa;
                if (pnt->fa!=nil)
                {
                        if (pnt->fa->ch[0]==pnt)
                        {
                                pnt->fa->ch[0]=now;
                        }else
                        {
                                pnt->fa->ch[1]=now;
                        }
                }
                pnt->fa=now;
                pnt->ch[p^1]=now->ch[p];
                if (now->ch[p]!=nil)now->ch[p]->fa=pnt;
                now->ch[p]=pnt;
                update(pnt);//注意顺序
                update(now);
        }
        void splay(node *now,node *top)
        {
                node *pnt;
                if (now==top)return ;
                while (now->fa!=top)
                {
                        pnt=now->fa;
                        if (pnt->ch[0]==now)
                        {
                                if (pnt->fa!=top&&pnt->fa->ch[0]==pnt)
                                {
                                        rotate(pnt,1);
                                }
                                rotate(now,1);
                        }else
                        {
                                if (pnt->fa!=top&&pnt->fa->ch[1]==pnt)
                                {
                                        rotate(pnt,0);
                                }
                                rotate(now,0);
                        }
                }
                if (top==nil)
                {
                        root=now;
                }
        }
        node *get_node(int rank)
        {
                node *now=root;
                if (now->siz<rank)throw "Not enough node";
                while (true)
                {
                        if (now->ch[0]->siz+1==rank)
                        {
                                return now;
                        }
                        if (now->ch[0]->siz+1<rank)
                        {
                                rank-=now->ch[0]->siz+1;
                                now=now->ch[1];
                        }else
                        {
                                now=now->ch[0];
                        }
                }
                return now;
        }
        node *get_min_node(node *now)
        {
                if (now==nil)throw "illegal call";
                //if (now==nil)return nil;
                while (now->ch[0]!=nil)
                {
                        now=now->ch[0];
                }
                return now;
        }
        pair<node*,node*> split(int pos)
        {
                if (pos==0)return make_pair(nil,root);
                splay(get_node(pos),nil);
                pair<node*,node*> ret;
                ret.first=root;
                ret.second=root->ch[1];
                root->ch[1]->fa=nil;
                root->ch[1]=nil;
                update(root);
                root=NULL;
                return ret;
        }
        node * merge(node * a1,node *a2)
        {
                if (a1==nil)return a2;
                if (a2==nil)return a1;
                root=a2;
                splay(get_min_node(a2),nil);
                root->ch[0]=a1;
                a1->fa=root;
                update(root);
                return root;
        }
        void insert(int pos,char ch)//插入ch后前面有pos个字符
        {
                node *now=Q.front();
                Q.pop();
                now->w=ch;
                if (pos==0)
                {
                        if (root==nil)
                        {
                                now->fa=nil;
                                now->ch[0]=now->ch[1]=nil;
                                now->siz=1;
                                root=now;
                                return ;
                        }
                        splay(get_min_node(root),nil);
                        now->fa=root;
                        root->ch[0]=now;
                        now->ch[0]=now->ch[1]=nil;
                        update(now);
                        update(root);
                        return ;
                }
                splay(get_node(pos),nil);
                if (root->ch[1]!=nil)splay(get_min_node(root->ch[1]),root);
                now->fa=root;
                now->ch[1]=root->ch[1];
                root->ch[1]->fa=now;
                root->ch[1]=now;
                now->ch[0]=nil;
                update(now);
                update(root);
                splay(now,nil);
                return ;
        }
        void insert2(int pos,char* str,int len)
        {
                if (len==0)return ;
                pair<node*,node*> pr1;
                pr1=split(pos);
                //scan(pr1.first);cout<<endl;
                //scan(pr1.second);cout<<endl;
                node *now=build_tree(str,0,len-1,nil);
                root=merge(pr1.first,merge(now,pr1.second));
        }
        node *build_tree(char *str,int l,int r,node *fa)
        {
                if (l>r)return nil;
                node *now=Q.front();
                int mid=(l+r)/2;
                Q.pop();
                now->fa=fa;
                now->w=str[mid];
                now->ch[0]=build_tree(str,l,mid-1,now);
                now->ch[1]=build_tree(str,mid+1,r,now);
                update(now);
                return now;
        }
        void recycle(node *now)
        {
                if (now==nil)return ;
                if (now->fa!=nil)
                {
                        if (now==now->fa->ch[0])
                        {
                                now->fa->ch[0]=nil;
                        }else if (now==now->fa->ch[1])
                        {
                                now->fa->ch[1]=nil;
                        }
                }
                recycle(now->ch[0]);
                recycle(now->ch[1]);
                Q.push(now);
        }

        void erase(int pos,int len)
        {
                pair<node*,node *> pr1,pr2;
                pr1=split(pos);
                root=pr1.second;
                pr2=split(len);
                recycle(pr2.first);
                root=merge(pr1.first,pr2.second);
        }
        void scan(node *now)
        {
                if (now==nil)return;
                if (now->siz!=now->ch[0]->siz+now->ch[1]->siz+1)
                {
                        throw "Size error";
                }
                if (now->ch[0]!=nil&&now->ch[0]->fa!=now)throw "Wrong ptr";
                if (now->ch[1]!=nil&&now->ch[1]->fa!=now)throw "Wrong ptr";
                scan(now->ch[0]);
                printf("%c",now->w);
                scan(now->ch[1]);
        }
        void scan2(node *now)
        {
                if (now==nil)return;
                scan2(now->ch[0]);
                printf("%c",now->w);
                scan2(now->ch[1]);
        }
        void print_str(int pos,int len)
        {
                if (!len){puts("");return ;}/**/
                if (pos==0)
                {
                        if (len==root->siz)
                        {
                                scan(root);
                                puts("");
                                return ;
                        }
                        splay(get_node(len+1),nil);
                        scan(root->ch[0]);
                        puts("");
                        return ;
                }
                splay(get_node(pos),nil);
                if (pos+len<=root->siz)splay(get_node(pos+len),root);
                node *temp=root->ch[0],*temp2=root->ch[1]->ch[1];
                root->ch[0]=nil;root->ch[1]->ch[1]=nil;
                scan2(root->ch[1]);puts("");
                root->ch[0]=temp;root->ch[1]->ch[1]=temp2;
                return ;
        }
}spt;
int i;
char str1[MAXN];
int main()
{
        //freopen("editor2.in","r",stdin);
        //freopen("out2.txt","w",stdout);
        try
        {
                int j,k,x,y;
                scanf("%d",&n);
                char od[10];
                int m,p;
                char *ptr;
                char ch;
                int nowad=0;
                int root2;
                for (i=0;i<n;i++)
                {
                        scanf("%s ",od);
                        switch (od[0])
                        {

                                case ‘M‘:

                                        scanf("%d\n",&x);
                                        nowad=x;
                                        break;
                                case ‘I‘:
                                        scanf("%d",&x);
                                        getchar();
                                        for (j=0;j<x;j++)
                                        {
                                                ch=getchar();
                                                if (ch<32||ch>126)
                                                {
                                                        j--;
                                                        continue;
                                                }
                                                str1[j]=ch;
                                                //if (i!=1)cerr<<ch<<endl;;
                                                //spt.insert(nowad+j,ch);
                                        }
                                        str1[x]=‘\0‘;
                                        spt.insert2(nowad,str1,x);
                                        if (x)ch=getchar();
                                        break;
                                case ‘D‘:
                                        scanf("%d\n",&x);
                                        spt.erase(nowad,x);
                                        break;
                                case‘G‘:
                                        scanf("%d\n",&x);
                                        spt.print_str(nowad,x);
                                        break;
                                case‘P‘:
                                        nowad--;
                                        break;
                                case‘N‘:
                                        nowad++;
                                        break;
                        }
                    /*    cout<<od<<" "<<x<<endl;
                        if (od[0]==‘I‘)cout<<str1<<endl;
                        cout<<"<<";spt.scan(spt.root);cout<<"["<<nowad<<"]";
                        cout<<endl;*/
                }
        }catch (const char* err)
        {
                cout<<err;
                return 0;
        }
        return 0;
}

BZOI 1507 [NOI2003] Editor

时间: 2024-08-11 01:34:39

BZOI 1507 [NOI2003] Editor的相关文章

1507: [NOI2003]Editor(块状链表)

1507: [NOI2003]Editor Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 4157  Solved: 1677[Submit][Status][Discuss] Description Input 输入文件editor.in的第一行是指令条数t,以下是需要执行的t个操作.其中: 为了使输入文件便于阅读,Insert操作的字符串中可能会插入一些回车符,请忽略掉它们(如果难以理解这句话,可以参考样例). 除了回车符之外,输入文件的所有字

BZOJ 1507 NOI2003 Editor Splay

题目大意: 1.将光标移动到某一位置 2.在光标后插入一段字符串 3.删除光标后的一段字符 4.输出光标后的一段字符 5.光标-- 6.光标++ 和1269很像的一道题,不过弱多了 几个问题需要注意: 1.插入的字符串中间居然会有回车!!没办法了,只能逐个字符进行读入,一旦读到'\n'或者'\r'就重新读入 2.题目描述中说Delete和Get操作后面一定会有足够的字符 纯属放P 连样例都没有足够的字符用来删除 所以删除时要和字符串长度取一个最小值 然后就水水地过去了~ 30%达成 今天是不是可

bzoj 1507: [NOI2003]Editor

1 #include<cstdio> 2 #include<iostream> 3 #include<ext/rope> 4 using namespace std; 5 using namespace __gnu_cxx; 6 crope list; 7 int n,now; 8 char ch[10],ch1[3000005]; 9 int main() 10 { 11 scanf("%d",&n); 12 for(int i=1;i&l

BZOJ1507 [NOI2003]Editor

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1507 [分析] 据说打完维修数列,什么数据结构题都是浮云了...这题似乎就是一个简化版咯. 这题的要求都和字母的值无关,而是与字母在序列中的位置有关...所以应当用位置关系建树的方法啦[就是每次找第k个位置就是这个节点的左边有k-1个节点] 首先预处理出两个虚拟节点作为开头和结尾[这个也是区间操作的比较基础的哦...]. 每次的添加就是找到光标和光标的下一个组成的区间,然后接在下一个的左

[NOI2003]Editor(块状链表)

传送门 看了看块状链表,就是数组和链表的合体. 看上去好高大尚,思想也很简单. 但是发现代码量也不是很小,而且代码理解起来也是费尽得很,倒不如splay用起来顺手. 在加上适用范围貌似不是特别广,所以只把模板贴在这,只当了解思想,暂时先不使用.(也不会用啊) 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<queue> 5 using namespace std;

NOI2003 文本编辑器editor

1507: [NOI2003]Editor Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 1908  Solved: 738[Submit][Status] Description Input 输入文件editor.in的第一行是指令条数t,以下是需要执行的t个操作.其中: 为了使输入文件便于阅读,Insert操作的字符串中可能会插入一些回车符,请忽略掉它们(如果难以理解这句话,可以参考样例). 除了回车符之外,输入文件的所有字符的ASCII码都在

7、8月刷题总结

准备开学了囧,7.8月刷题记录,以后好来复习,并且还要好好总结! 数据结构: splay: [BZOJ]1503: [NOI2004]郁闷的出纳员(Splay) [BZOJ]1269: [AHOI2006]文本编辑器editor(Splay) [BZOJ]1507: [NOI2003]Editor(Splay) treap: [BZOJ]1862: [Zjoi2006]GameZ游戏排名系统 & 1056: [HAOI2008]排名系统(treap+非常小心) [BZOJ]3224: Tyvj

博客开更!!

好颓啊!!  做题好慢!! 各种错误!! 1014: [JSOI2008]火星人prefix 额 splay没啥说的 字符串hash蒟蒻不会啊 搞半天才懂 好玄学啊 unsigned的自然溢出也是玄学啊 (话说我 int的自然溢出也A了smg?? 1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std

小结:平衡树

概要: 平衡树大概是最常用的高级数据结构了,而treap用来进行一般的信息维护,splay用来进行高级的信息维护(比如区间操作.lct等)(map.set党自重QAQ). 技巧及注意: 细节十分多. treap中如果设小根堆的话(最好设小根堆),null的重量要设置为inf. 平衡树中的重复元素两种处理方法,看情况使用. 平衡树中的rank和select要和上一种注意事项结合起来,多想想. splay中如果写lct要特判根.treap很多地方要传指针引用,splay完全不必.写好后最好手造几组h