欢迎访问~原文出处——博客园-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
*/