[AHOI2006]文本编辑器

[AHOI2006]文本编辑器

[洛谷链接](https://www.luogu.org/problemnew/show/P4567)

  尽管这道题不是思路不难,代码量也不大不到80行(没忍住压了行),但是有一些比较烦人的细节,所以在许多次的尝试好才成功AC。

## Solution

  显然这是一道平衡树的板子题(默认大家都会平衡树)。不难发现的是不论是插入还是删除,平衡树上每个结点中序遍历后的相对位置不会发生改变,所以可也愉快地省去平衡树结点的关键字信息,可以直接用寻找排名的方式来确定结点的位置。插入、删除、区间翻转操作的思路也很简单,可以理解成把不要的结点全部旋走,只留下要使用的,进行一些操作,显然代码也就三四行,异常简单。剩下的就是按照题意模拟了,时间复杂度是 $ O(nlog_2n) $ 级别的,无压力AC。此题最坑的应该是读入吧,毕竟坑可我好长时间,貌似也被空间坑了。下面献出我的splay AC代码(好像只会splay了)。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <bitset>
#define N 2500005
#define ll long long
#define rint register int
using namespace std;
inline int read (){
  register int num,sign=1;register char c;
  while (((c=getchar())<'0'||c>'9')&&c!='-');c=='-'?num=sign=0:num=c-48;
  while ((c=getchar())>='0'&&c<='9')num=(num<<3)+(num<<1)+(c-48);
  return sign?num:-num;
}
int cnt,root,len,now,x,n;
int l[N],r[N],f[N],size[N];
bool tag[N];
char data[N],S[N],opt[10],c;
inline void pushup(rint x){size[x]=size[l[x]]+size[r[x]]+1;}
inline void pushdown(rint x){
  if(!tag[x])return;
  tag[l[x]]^=1;tag[r[x]]^=1;tag[x]^=1;swap(l[x],r[x]); 
}
inline void rotate(rint x){
  rint y=f[x],z=f[f[x]];
  if(l[z]==y)l[z]=x;else r[z]=x;f[x]=z;
  if(l[y]==x){l[y]=r[x];f[r[x]]=y;r[x]=y;f[y]=x;}else{r[y]=l[x];f[l[x]]=y;l[x]=y;f[y]=x;} 
  l[0]=r[0]=0;
  pushup(y);pushup(x);
}
inline void splay(rint x,rint rt){
  for(;f[x]!=rt;rotate(x)){
  	int y=f[x],z=f[f[x]];pushdown(x);
  	if(z==rt)continue;
  	rotate((l[z]==y)^(l[y]==x)?x:y);
  }
  if(rt==0)root=x;
}
inline int rnk(rint x,rint k){
  pushdown(x);
  if(size[l[x]]+1==k)return x;
  if(size[l[x]]>=k)return rnk(l[x],k);
  return rnk(r[x],k-size[l[x]]-1);
}
inline void erase(rint L,rint R){
  rint p=rnk(root,L),s=rnk(root,R+2);
  splay(p,0);splay(s,p);l[s]=f[l[s]]=0;splay(s,0);
}
inline void insert(rint id,rint rt){
  rint p=rnk(root,id),s=rnk(root,id+1);
  splay(p,0);splay(s,p);l[s]=rt;f[rt]=s;splay(s,0);
}
inline void Rev(rint L,rint R){
  rint p=rnk(root,L),s=rnk(root,R+2);
  splay(p,0);splay(s,p);tag[l[s]]^=1;
}
inline void build(rint L,rint R,int &u,rint fa){
  if(L>R)return;
  rint mid=(L+R)>>1;u=++len;
  size[u]=1;data[u]=S[mid];f[u]=fa;
  build(L,mid-1,l[u],u);build(mid+1,R,r[u],u);
  pushup(u);
}
int main(){
  n=read();S[1]=31;S[2]=127; 
  build(1,2,root,0);now=0;
  for(rint i=1;i<=n;++i){rint rt=0;
  	scanf("%s",opt+1);//注意读入有坑
  	if(opt[1]=='M')now=read();
  	if(opt[1]=='I'){scanf("%d",&x);getchar();for(rint j=1;j<=x;++j)S[j]=getchar();build(1,x,rt,0);insert(now+1,rt);}
  	if(opt[1]=='D'){scanf("%d",&x);erase(now+1,now+x);}
  	if(opt[1]=='G'){c=data[rnk(root,now+2)];if(c!='\n')putchar(c);puts("");}
  	if(opt[1]=='R'){scanf("%d",&x);Rev(now+1,now+x);}
  	if(opt[1]=='P')--now; 
  	if(opt[1]=='N')++now;;
  }
}
posted @ 2019-01-24 22:37  利姆鲁·特恩佩斯特  阅读(103)  评论(0)    收藏  举报