• 【BZOJ1269/1507】[AHOI2006]文本编辑器editor Splay


    【BZOJ1269】[AHOI2006]文本编辑器editor

    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操作不会把光标移动到非法位置。 输入文件没有错误。

    题解:依旧是Splay裸题,但是有一点很坑:

    就是gets()在读入整行时会忽略前导的空格,于是我们必须在读入上一个变量时加一个scanf("%*c")或者getchar()来防止将空格省略掉,或者一个一个字符读进来

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    int n,m,root,now,tot;
    struct node
    {
    	int ch[2],fa,v,siz,tag;
    }s[1024*2048+10];
    char str[1024*2048+10];
    void pushup(int x)
    {
    	s[x].siz=s[s[x].ch[0]].siz+s[s[x].ch[1]].siz+1;
    }
    void pushdown(int x)
    {
    	if(s[x].tag)
    	{
    		swap(s[x].ch[0],s[x].ch[1]);
    		s[s[x].ch[0]].tag^=1,s[s[x].ch[1]].tag^=1;
    		s[x].tag=0;
    	}
    }
    int find(int y,int x)
    {
    	if(!x)	return 0;
    	pushdown(x);
    	if(s[s[x].ch[0]].siz>=y)	return find(y,s[x].ch[0]);
    	if(s[s[x].ch[0]].siz+1==y)	return x;
    	return find(y-s[s[x].ch[0]].siz-1,s[x].ch[1]);
    }
    void rotate(int x,int &k)
    {
    	int y=s[x].fa,z=s[y].fa,d=(x==s[y].ch[1]);
    	if(z)	s[z].ch[(y==s[z].ch[1])]=x;
    	if(y==k)	k=x;
    	s[x].fa=z,s[y].fa=x,s[y].ch[d]=s[x].ch[d^1];
    	if(s[x].ch[d^1])	s[s[x].ch[d^1]].fa=y;
    	s[x].ch[d^1]=y;
    	pushup(y),pushup(x);
    }
    void splay(int x,int &k)
    {
    	while(x!=k)
    	{
    		int y=s[x].fa,z=s[y].fa;
    		if(y!=k)
    		{
    			if((x==s[y].ch[0])^(y==s[z].ch[0]))	rotate(x,k);
    			else	rotate(y,k);
    		}
    		rotate(x,k);
    	}
    }
    void build(int l,int r,int last,int d)
    {
    	if(l>r)	return ;
    	int tmp=++tot,mid=l+r>>1;
    	s[tmp].fa=last;
    	s[last].ch[d]=tmp;
    	s[tmp].v=str[mid]-32;
    	build(l,mid-1,tmp,0),build(mid+1,r,tmp,1);
    	pushup(tmp);
    }
    int main()
    {
    	scanf("%d",&n);
    	s[1].ch[1]=2,s[1].siz=2,s[2].siz=1,s[2].fa=1,now=root=1,tot=2;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%s",str);
    		switch(str[0])
    		{
    			case 'M':
    			{
    				scanf("%d",&now),now++;
    				break;
    			}
    			case 'I':
    			{
    				scanf("%d%*c",&m);
    				gets(str);
    				splay(find(now,root),root),splay(find(now+1,root),s[root].ch[1]);
    				build(0,m-1,s[root].ch[1],0);
    				pushup(s[root].ch[1]),pushup(root);
    				break;
    			}
    			case 'D':
    			{
    				scanf("%d",&m);
    				splay(find(now,root),root),splay(find(now+m+1,root),s[root].ch[1]);
    				s[s[root].ch[1]].ch[0]=0;
    				pushup(s[root].ch[1]),pushup(root);
    				break;
    			}
    			case 'R':
    			{
    				scanf("%d",&m);
    				splay(find(now,root),root),splay(find(now+m+1,root),s[root].ch[1]);
    				s[s[s[root].ch[1]].ch[0]].tag^=1;
    				break;
    			}
    			case 'G':
    			{
    				printf("%c
    ",s[find(now+1,root)].v+32);
    				break;
    			}
    			case 'P':
    			{
    				now--;
    				break;
    			}
    			case 'N':
    			{
    				now++;
    				break;
    			}
    		}
    	}
    	return 0;
    }
    

    【BZOJ1507】[NOI2003]editor

    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

    题解:本题注意事项:

    1.读入有换行,要一个一个字符读入

    2.网上有人说要防止溢出,感觉没啥用

    3.输出时候不要太麻烦哦~

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    int n,m,root,now,tot;
    struct node
    {
    	int ch[2],fa,v,siz;
    }s[1024*2048+10];
    char str[1024*2048+10];
    void pushup(int x)
    {
    	s[x].siz=s[s[x].ch[0]].siz+s[s[x].ch[1]].siz+1;
    }
    int find(int y,int x)
    {
    	if(!x)	return 0;
    	if(s[s[x].ch[0]].siz>=y)	return find(y,s[x].ch[0]);
    	if(s[s[x].ch[0]].siz+1==y)	return x;
    	return find(y-s[s[x].ch[0]].siz-1,s[x].ch[1]);
    }
    void rotate(int x,int &k)
    {
    	int y=s[x].fa,z=s[y].fa,d=(x==s[y].ch[1]);
    	if(z)	s[z].ch[(y==s[z].ch[1])]=x;
    	if(y==k)	k=x;
    	s[x].fa=z,s[y].fa=x,s[y].ch[d]=s[x].ch[d^1];
    	if(s[x].ch[d^1])	s[s[x].ch[d^1]].fa=y;
    	s[x].ch[d^1]=y;
    	pushup(y),pushup(x);
    }
    void splay(int x,int &k)
    {
    	while(x!=k)
    	{
    		int y=s[x].fa,z=s[y].fa;
    		if(y!=k)
    		{
    			if((x==s[y].ch[0])^(y==s[z].ch[0]))	rotate(x,k);
    			else	rotate(y,k);
    		}
    		rotate(x,k);
    	}
    }
    void build(int l,int r,int last,int d)
    {
    	if(l>r)	return ;
    	int tmp=++tot,mid=l+r>>1;
    	s[tmp].fa=last,s[last].ch[d]=tmp,s[tmp].v=str[mid]-32;
    	build(l,mid-1,tmp,0),build(mid+1,r,tmp,1);
    	pushup(tmp);
    }
    void print(int x)
    {
    	if(s[x].ch[0])	print(s[x].ch[0]);
    	putchar(s[x].v+32);
    	if(s[x].ch[1])	print(s[x].ch[1]);
    }
    int main()
    {
    	scanf("%d",&n);
    	int i,j;
    	s[1].ch[1]=2,s[1].siz=2,s[2].siz=1,s[2].fa=1,now=root=1,tot=2;
    	for(i=1;i<=n;i++)
    	{
    		scanf("%s",str);
    		switch(str[0])
    		{
    			case 'M':{scanf("%d",&now),now++;	break;}
    			case 'I':
    			{
    				scanf("%d%*c",&m);
    				for(j=0;j<m;j+=(str[j]!='
    '&&str[j]!='
    '))	str[j]=getchar();
    				splay(find(now,root),root),splay(find(now+1,root),s[root].ch[1]);
    				build(0,m-1,s[root].ch[1],0);
    				pushup(s[root].ch[1]),pushup(root);
    				break;
    			}
    			case 'D':
    			{
    				scanf("%d",&m);
    				splay(find(now,root),root),splay(find(now+m+1,root),s[root].ch[1]);
    				s[s[root].ch[1]].ch[0]=0;
    				pushup(s[root].ch[1]),pushup(root);
    				break;
    			}
    			case 'G':
    			{
    				scanf("%d",&m);
    				splay(find(now,root),root),splay(find(now+m+1,root),s[root].ch[1]);
    				print(s[s[root].ch[1]].ch[0]);
    				printf("
    ");
    				break;
    			}
    			case 'P':{now--;	break;}
    			case 'N':{now++;	break;}
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    ssh实现免密码登录和文件传输
    linux后台执行程序相关命令
    orchestrator
    curl下载安装与使用
    goland使用
    mysql集群
    consul理解
    my.cnf
    数据库的表设计
    项目常见面试问题
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6497999.html
Copyright © 2020-2023  润新知