[AHOI2006]文本编辑器
[AHOI2006]文本编辑器
[洛谷链接](https://www.luogu.org/problemnew/show/P4567) 尽管这道题不是思路不难,代码量也不大不到80行(没忍住压了行),但是有一些比较烦人的细节,所以在许多次的尝试好才成功AC。
显然这是一道平衡树的板子题(默认大家都会平衡树)。不难发现的是不论是插入还是删除,平衡树上每个结点中序遍历后的相对位置不会发生改变,所以可也愉快地省去平衡树结点的关键字信息,可以直接用寻找排名的方式来确定结点的位置。插入、删除、区间翻转操作的思路也很简单,可以理解成把不要的结点全部旋走,只留下要使用的,进行一些操作,显然代码也就三四行,异常简单。剩下的就是按照题意模拟了,时间复杂度是 $ 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;;
}
}

浙公网安备 33010602011771号