jzoj3658 [NOI2014模拟] 文本编辑器(editor)

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

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;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值