BZOJ1269 [AHOI2006]文本编辑器editor splay
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ1269
题意概括
你要搞一个文本编辑器。
主要支持一下操作:
插入字符串、删除字符串、区间字符串翻转、输出光标后的一个字符。
详细见原题。
题解
splay板子题。
一开始我是一个一个字符弄到splay里面去,结果Tle了。
所以,我们要一段一段的插入。删除也同理,详见代码
代码
#include <cstring> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cmath> using namespace std; const int MaxL=2100000; char str[MaxL]; struct Splay{ int root,cnt,fa[MaxL],son[MaxL][2],size[MaxL],val[MaxL],rev[MaxL]; void clear(){ root=cnt=0; memset(size,0,sizeof size); memset(son,0,sizeof son); memset(val,0,sizeof val); memset(rev,0,sizeof rev); memset(fa,0,sizeof fa); } void print(){ puts("Splay.Print_________________"); printf("root=%d\n",root); for (int i=1;i<=cnt;i++) printf("%d:fa=%d,son=(%d,%d),size=%d,val=%c,rev=%d\n" ,i,fa[i],son[i][0],son[i][1],size[i],(char)val[i],rev[i]); puts("Splay.Print_Over============"); } void dfs(int rt){ pushdown(rt); if (son[rt][0]) dfs(son[rt][0]); printf("%c",val[rt]); if (son[rt][1]) dfs(son[rt][1]); } void printstr(){ dfs(root);puts(""); } void pushup(int x){size[x]=size[son[x][0]]+size[son[x][1]]+1;} void pushrev(int x){ if (!x) return; rev[x]^=1; swap(son[x][0],son[x][1]); } void pushdown(int x){ if (rev[x]){ rev[x]=0; pushrev(son[x][0]); pushrev(son[x][1]); } } void pushadd(int x){ if (fa[x]) pushadd(fa[x]); pushdown(x); } int wson(int x){return son[fa[x]][1]==x;} void rotate(int x){ if (!fa[x]) return; int y=fa[x],z=fa[y],L=wson(x),R=L^1; if (z) son[z][wson(y)]=x; fa[x]=z,fa[y]=x,fa[son[x][R]]=y; son[y][L]=son[x][R],son[x][R]=y; pushup(y); pushup(x); } void splay(int x,int k){ pushadd(x); if (k==0) root=x; while (fa[x]!=k){ int y=fa[x],z=fa[y]; if (z!=k) rotate(wson(x)==wson(y)?y:x); rotate(x); } } void splay(int x){ splay(x,0); } void add(int &x,int pre,int befo,int v){ if (!x){ val[x=++cnt]=v,fa[x]=pre,size[x]=1; son[x][0]=son[x][1]=rev[x]=0; splay(x); return; } pushdown(x); size[x]++; if (size[son[x][0]]>=befo) add(son[x][0],x,befo,v); else add(son[x][1],x,befo-size[son[x][0]]-1,v); } void add(int befo,int v){add(root,0,befo,v);} void build(int &x,int pre,int L,int R){ if (L>R) return; int mid=(L+R)>>1; fa[x=++cnt]=pre,val[x]=str[mid],rev[x]=0,size[x]=1,son[x][0]=son[x][1]=0; build(son[x][0],x,L,mid-1); build(son[x][1],x,mid+1,R); pushup(x); } int findkth(int x,int k){ pushdown(x); if (k==size[son[x][0]]+1) return x; if (k<=size[son[x][0]]) return findkth(son[x][0],k); else return findkth(son[x][1],k-size[son[x][0]]-1); } int findkth(int k){return findkth(root,k);} int findL(int x){ pushdown(x); if (son[x][0]) return findL(son[x][0]); return x; } int findR(int x){ pushdown(x); if (son[x][1]) return findR(son[x][1]); return x; } void erase(int L,int R){ splay(findkth(L-1)); splay(findkth(R+1),root); fa[son[son[root][1]][0]]=0; son[son[root][1]][0]=0; pushup(son[root][1]); pushup(root); } }s; int n,p; int main(){ scanf("%d",&n); s.clear(); s.add(1,'#'),s.add(1,'#'); p=0; for (int c=1;c<=n;c++){ // s.print(); // s.printstr(); char op[10]; int a; scanf("%s",op); if (op[0]=='M') scanf("%d",&p); else if (op[0]=='I'){ scanf("%d%*c",&a); gets(str+1); s.splay(s.findkth(p+1)); s.splay(s.findkth(p+2),s.root); s.build(s.son[s.son[s.root][1]][0],s.son[s.root][1],1,a); } else if (op[0]=='D'){ scanf("%d",&a); s.erase(p+2,p+1+a); } else if (op[0]=='R'){ scanf("%d",&a); s.splay(s.findkth(p+1)); s.splay(s.findkth(p+a+2),s.findkth(p+1)); s.pushrev(s.son[s.son[s.root][1]][0]); } else if (op[0]=='G') printf("%c\n",(char)s.val[s.findkth(p+2)]); else if (op[0]=='P') p--; else if (op[0]=='N') p++; } return 0; } /* 10 Insert 13 Balanced eert Move 2 Delete 5 Next Insert 7 editor Move 0 Get Move 11 Rotate 4 Get */