Description
给定m个操作,包括插入一个字符、删除一段连续的字符、翻转一段连续的字符、复制一段连续的字符到指定位置、查询指定位置上的字符
Solution
第一眼以为splay水题,结果发现并不会复制操作。气急败坏地写了个链表怒艹20分
这里实际上是可持久化treap。所谓可持久化treap是一种无旋转操作的treap,通过split(分裂)和merge(合并)维护区间。没有旋转操作的特性使得它能保存父子结构,每次split和merge的时候新建节点就能可持久化了。考虑一下以后都用这个替换splay好了
顺便get到了一种神奇的伪随机数写法,大概就是随便乘然后自然溢出之类的
注意这道题有点卡常,一气之下硬上了各种神奇的优化
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
typedef std:: pair<int,int> pair;
typedef long long LL;
const int N=200005;
struct treeNode{int son[2],fa,size,lazy; char ch;}t[N*101];
int root,cnt,ra;
__attribute__((optimize("O2")))
inline int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
__attribute__((optimize("O2")))
inline int get_big_letter() {
char ch=getchar();
while (ch<'A'||ch>'Z') ch=getchar();
return ch;
}
__attribute__((optimize("O2")))
inline int get_small_letter() {
char ch=getchar();
while (ch<'a'||ch>'z') ch=getchar();
return ch;
}
__attribute__((optimize("O2")))
inline int rand() {return ra=((LL)ra*3450934+484524)%2147483647;}
__attribute__((optimize("O2")))
inline int new_node(int x) {t[++cnt]=t[x]; return cnt;}
__attribute__((optimize("O2")))
inline void push_up(int x) {
t[x].size=t[t[x].son[0]].size+t[t[x].son[1]].size+1;
}
__attribute__((optimize("O2")))
inline void push_down(int x) {
if (!t[x].lazy||!x) return ;
if (t[x].son[0]) {
t[x].son[0]=new_node(t[x].son[0]);
std:: swap(t[t[x].son[0]].son[0],t[t[x].son[0]].son[1]);
t[t[x].son[0]].lazy^=1;
}
if (t[x].son[1]) {
t[x].son[1]=new_node(t[x].son[1]);
std:: swap(t[t[x].son[1]].son[0],t[t[x].son[1]].son[1]);
t[t[x].son[1]].lazy^=1;
}
t[x].lazy=0;
push_up(x);
}
__attribute__((optimize("O2")))
inline pair split(int x,int y) {
if (!x) return pair(0,0);
push_down(x);
pair tmp; int now;
if (t[t[x].son[0]].size>=y) {
tmp=split(t[x].son[0],y);
now=new_node(x);
t[now].son[0]=tmp.second;
push_up(now);
return pair(tmp.first,now);
} else {
tmp=split(t[x].son[1],y-t[t[x].son[0]].size-1);
now=new_node(x);
t[now].son[1]=tmp.first;
push_up(now);
return pair(now,tmp.second);
}
}
__attribute__((optimize("O2")))
inline int merge(int x,int y) {
if (!x||!y) return x+y;
push_down(x); push_down(y);
int tmp;
if (rand()%(t[x].size+t[y].size)<t[x].size) {
tmp=new_node(x);
t[tmp].son[1]=merge(t[tmp].son[1],y);
} else {
tmp=new_node(y);
t[tmp].son[0]=merge(x,t[tmp].son[0]);
}
push_up(tmp);
return tmp;
}
__attribute__((optimize("O2")))
int main(void) {
freopen("editor.in","r",stdin);
freopen("editor.out","w",stdout);
root=cnt=t[1].size=1;
int m=read(); int reec=m;
pair ret1,ret2;
while (m--) {
// printf("%d\n",reec-m);
char opt=get_big_letter();
if (opt=='I') {
int x=read(); char ch=get_small_letter();
ret1=split(root,x);
//pair ret2=split(ret1.second,1);
t[++cnt].ch=ch; t[cnt].size=1;
root=merge(ret1.first,merge(cnt,ret1.second));
//root=merge(ret1.first,merge(merge(cnt,ret2.first),ret2.second));
} else if (opt=='D') {
int l=read(),r=read();
ret1=split(root,l-1);
ret2=split(ret1.second,r-l+1);
root=merge(ret1.first,ret2.second);
} else if (opt=='C') {
int l=read(),r=read(),x=read();
ret1=split(root,l-1);
ret2=split(ret1.second,r-l+1);
// int tmp=new_node(ret2.first);
int tmp=ret2.first;
root=merge(ret1.first,merge(ret2.first,ret2.second));
ret1=split(root,x);
ret2=split(ret1.second,1);
root=merge(ret1.first,merge(merge(tmp,ret2.first),ret2.second));
} else if (opt=='R') {
int l=read(),r=read();
ret1=split(root,l-1);
ret2=split(ret1.second,r-l+1);
int tmp=new_node(ret2.first);
t[tmp].lazy^=1; std:: swap(t[tmp].son[0],t[tmp].son[1]);
root=merge(ret1.first,merge(tmp,ret2.second));
} else if (opt=='Q') {
int x=read();
int now=root; push_down(now);
while (233) {
if (t[t[now].son[0]].size+1==x) break;
if (t[t[now].son[0]].size+1>x) now=t[now].son[0];
else {
x-=t[t[now].son[0]].size+1;
now=t[now].son[1];
}
push_down(now);
}
putchar(t[now].ch);
}
}
return 0;
}

本文介绍了一种使用可持久化Treap解决编辑器模拟问题的方法,该问题涉及字符的插入、删除、翻转及复制等操作。文章详细讲解了如何利用Treap的分裂和合并操作来高效地处理这些编辑任务。
392

被折叠的 条评论
为什么被折叠?



