【NOI2003T2】文本编辑器Editor-伸展树数列操作

原创 2016年08月29日 22:15:03

题目:文本编辑器Editor

做法:此题用伸展树(Splay Tree)数列操作的方法来进行插入、删除和提取操作。如果伸展树的中序遍历为要操作的序列,我们就可以这样提取字符串:如要提取从第i个元素开始的len个元素,就将第i个元素所在的节点旋转到根,再将第i+len+1个元素所在的节点所在的节点旋转到根的下面,于是根的右子树的左子树就是我们所要提取的区间了,输出的话只要按中序遍历遍历一遍这棵子树并输入所代表的字符串即可。这些操作的细节在很多网上的教程都有,在这里就不赘述了。注意插入字符串时,要尽可能将其所形成的子树的深度缩小,所以我们可以运用类似线段树的构建方法来构建树。还要注意,直接这样存储会出现一些隐蔽的问题,要在区间的左右生成两个边界节点,才能解决此问题。

以下是本人代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 1024*1024
using namespace std;
int t,rt=0,top=0,l=0,len,ch[2*M+10][2],pre[2*M+10],siz[2*M+10];
char op[20],in[2*M+10],val[2*M+10];
bool flag;

void newnode(int &x,char c,int f)
{
  x=++top;
  ch[x][0]=ch[x][1]=0;pre[x]=f;
  val[x]=c;siz[x]=1;
}

void pushup(int x) //用x两个儿子的值更新节点x
{
  siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
}

void buildtree(int &x,int l,int r,int f) //对要插入的区间构建子树
{
  if (l>r) return;
  int mid=(l+r)>>1;
  newnode(x,in[mid],f);
  buildtree(ch[x][0],l,mid-1,x);
  buildtree(ch[x][1],mid+1,r,x);
  pushup(x);
}

void read(int len) //读入要插入的字符串
{
  int i=0;
  while(i<len)
  {
    scanf("%c",&in[i+1]);
	if (in[i+1]!='\n') i++;
  }
}

void rotate(int x,bool f) //将节点x绕其父节点向f方向旋转,f=0为左,f=1为右
{
  int y=pre[x];
  ch[y][!f]=ch[x][f];
  pre[ch[x][f]]=y;
  ch[x][f]=y;
  if (pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
  pre[x]=pre[y];pre[y]=x;
  pushup(y);
}

void Splay(int x,int goal) //伸展操作,将节点x旋转到节点goal下面(goal为0时表示旋转到根)
{
  while(pre[x]!=goal)
  {
    if (pre[pre[x]]==goal) rotate(x,ch[pre[x]][0]==x);
	else
	{
	  int y=pre[x],z=pre[y];
	  bool f=(ch[z][1]==y);
	  if (ch[y][f]==x) rotate(y,!f),rotate(x,!f);
	  else rotate(x,f),rotate(x,!f);
	}
  }
  pushup(x);
  if (goal==0) rt=x;
}

void rotateto(int k,int goal) //将中序遍历第k个的节点旋转到节点goal下面(goal为0时表示旋转到根)
{
  int x=rt;
  while(siz[ch[x][0]]+1!=k)
  {
    if (siz[ch[x][0]]+1<k) {k-=siz[ch[x][0]]+1;x=ch[x][1];}
	else x=ch[x][0];
  }
  Splay(x,goal);
}

void insert(int l,int len) //在第l个字符后插入长度为len的字符串
{
  rotateto(l+1,0);
  rotateto(l+2,rt);
  buildtree(ch[ch[rt][1]][0],1,len,ch[rt][1]);
  pushup(ch[rt][1]);pushup(rt);
}

void del(int l,int len) //删除第l个字符后的len个字符
{
  rotateto(l+1,0);
  rotateto(l+len+2,rt);
  ch[ch[rt][1]][0]=0;
  pushup(ch[rt][1]);pushup(rt);
}

void vis(int x) //中序遍历以x为根的子树并输出其代表的字符串
{
  if (ch[x][0]) vis(ch[x][0]);
  if (val[x]!='\n') printf("%c",val[x]);
  if (ch[x][1]) vis(ch[x][1]);
}

void getn(int l,int len) //提取第l个字符后的长度为n的字符串并输出
{
  rotateto(l+1,0);
  rotateto(l+len+2,rt);
  if (flag) printf("\n");
  else flag=1;
  vis(ch[ch[rt][1]][0]);
}

int main()
{
  scanf("%d",&t);
  ch[0][0]=ch[0][1]=pre[0]=siz[0]=flag=0;
  newnode(rt,'\n',0);
  newnode(ch[rt][1],'\n',rt); //生成两个边界节点
  for(int i=1;i<=t;i++)
  {
    scanf("%s",op);
	if (op[0]=='P') l--;
	if (op[0]=='N') l++;
	if (op[0]=='M') scanf("%d",&l);
    if (op[0]=='I')
	{
	  scanf("%d",&len);
	  read(len);
	  insert(l,len);
	}
	if (op[0]=='D')
	{
	  scanf("%d",&len);
	  del(l,len);
	}	
	if (op[0]=='G')
	{
	  scanf("%d",&len);
	  getn(l,len);
	}
  }
  
  return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

Unity3D 场景编辑器扩展学习笔记-Editor

PS:适合对UnityEditor类有一些了解的童鞋阅读,我没有完全研究透这套东西,暂时先学到哪写到哪吧。 重要的类:Editor,EditorWindow,GUILayout,Handles,Eve...
  • kun1234567
  • kun1234567
  • 2014年02月18日 19:46
  • 24951

Unity Editor 基础篇(三):自定义窗口

本文参自:http://mp.weixin.qq.com/s/tMSAIND4Pq0farn2jY8rwg本文为本人学习上连接的笔记有改动,请点击以上链接查看原文,尊重楼主知识产权。Unity Edi...
  • qq_33337811
  • qq_33337811
  • 2017年03月15日 15:50
  • 6254

UNITY3D拓展编辑器 - InspectorEditor(属性编辑器)1

前文:    本章节会对InspectorEditor(属性编辑器)的创建方式进行叙述. 正文:   1.代码最终效果        2. 架构阐述   一个InspectorEd...
  • oCaiHong1
  • oCaiHong1
  • 2016年05月18日 09:57
  • 2018

BZOJ 1269 [AHOI2006]文本编辑器editor Splay伸展树

题目大意:类似于我们正常输入文本,现在模拟这样的一个功能。它支持: 1.将光标移动到第k个字符前 2.在光标后面加入长度为l的字符串 3.删除光标后面l个字符 4.将光标后面l个字符翻转 5...
  • jiangyuze831
  • jiangyuze831
  • 2014年09月13日 20:00
  • 1063

[bzoj1269]文本编辑器editor [bzoj1500]维修数列

1269: [AHOI2006]文本编辑器editorTime Limit: 10 Sec Memory Limit: 162 MB Submit: 2540 Solved: 923 [Sub...
  • FZHvampire
  • FZHvampire
  • 2015年08月14日 15:17
  • 1498

【BZOJ1269】文本编辑器editor(AHOI2006)-NOI原题升级版

【BZOJ1269】文本编辑器editor(AHOI2006)-NOI原题升级版
  • Maxwei_wzj
  • Maxwei_wzj
  • 2016年08月30日 20:56
  • 241

NOI2003 文本编辑器 块状链表

刚看到这道题时还啥也不懂,后来被安利了块状链表,于是搞了好久,现在发现Splay也可以搞…. 下面是块状链表搞法….#include #include #include #include #incl...
  • u011757339
  • u011757339
  • 2016年07月04日 20:06
  • 150

Splay 维护序列 / 块状链表 NOI 2003 - 文本编辑器

Splay / 块状链表
  • lycheng1215
  • lycheng1215
  • 2017年12月05日 21:41
  • 23

Splay Tree(伸展树)[NOI2005]维修数列

伸展树         概述:不同于线段树的以空间换取时间,用多余的节点去存储多余的信息,来达到降低时间复杂度。SplayTree基于一种更简单的思想,为了使整个查找时间更小,被查频率高的那些条目就应...
  • shiqi_614
  • shiqi_614
  • 2013年08月13日 09:25
  • 2353

【伸展树】【NOI2005】维护数列

Input 输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。第2行包含N个数字,描述初始时的数列。以下M行,每行一条命令,格式参见问题描述中的表格。 Output...
  • Whjpji
  • Whjpji
  • 2012年06月04日 20:00
  • 2043
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【NOI2003T2】文本编辑器Editor-伸展树数列操作
举报原因:
原因补充:

(最多只允许输入30个字)