【BZOJ 1269】 [AHOI2006]文本编辑器editor

【链接】 我是链接,点我呀:)
【题意】

在这里输入题意

【题解】

/*
    【move k】 指令。直接 把pos改成k.表示改变光标位置

    【insert n s】,在pos后面插入一个长度为n的字符串。
    这个操作。
    我们可以先找出第pos个节点x和第pos+1个节点y
    (这里其实就是找第pos小的数,在splay上,加一个size大小域,找第k小即可。)
    (伸展树在旋转的过程中,不会影响性质,即,它中序遍历的结果始终是字符串s1..n)

    我们执行splay x 0
    再执行splay y x
    然后显然y节点在x的右儿子上。
    那么,此时,我们新建一颗节点为插入的字符串的子树root
    然后把root放在y的左子树

    然后我们新建一颗子树,把它加在y的左儿子上。

        我们在插入节点的时候。放在左儿子和右儿子。
        其实就是约束了这个点和其父亲节点的先后关系。
        左儿子在前.右儿子的话就是在后。
        也正因为如此。
        我们才能保证中序遍历结果为s[1..n]

    【delete(n)】 找出第pos个节点x和第pos+1+n个节点y.然后同样的splay(x,0)、splay(y,x),然后把y的左子树删掉就可以了。

    【rotate n】一样。找到pos和pos+1+n两个节点x,y 然后spay(x,0),splay(y,x) 然后把y的左儿子打上翻转标记。(这里后序的我不知道怎么处理
     (什么时候要push_down?

    【get】就直接输出第pos个节点的字符就好。

    【prev】 pos--;

    【next] pos++;

*/

【注意】
push_down只要加在Rank函数的开头就好。
因为每次从根到root.
一路上都会把标记给Push_down了
那么rotate里面就不需要push_down了。

【代码】

#include <bits/stdc++.h>
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define all(x) x.begin(),x.end()
#define pb push_back
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define which(x) (ch[fa[x]][1]==x)
using namespace std;

const double pi = acos(-1);
const int dx[4] = {0,0,1,-1};
const int dy[4] = {1,-1,0,0};
const int N = 2*1024*1024;

int n,siz[N+100],fa[N+10],tag[N+10],tot,pos;
int ch[N+10][2],root;
char s[10],S[N+10],str[N+10];

void push_up(int x){
    siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
}

void push_down(int x){
    if (tag[x]>0){
        tag[x] = 0;
        tag[ch[x][0]]^=1;tag[ch[x][1]] ^= 1;
        swap(ch[x][0],ch[x][1]);
    }
}

int Rank(int x, int k)
{
    push_down(x);
    if (siz[ch[x][0]] >= k)
        return Rank(ch[x][0], k);
    else
        if (k == siz[ch[x][0]] + 1)
            return x;
        else
            return Rank(ch[x][1], k - siz[ch[x][0]] - 1);
}

void Rotate(int x)
{
    int f = fa[x];
    bool k = which(x);
    ch[f][k] = ch[x][!k];
    ch[x][!k] = f;
    ch[fa[f]][which(f)] = x;
    fa[ch[f][k]] = f;
    fa[x] = fa[f];
    fa[f] = x;
    siz[x] = siz[f];
    push_up(f);
}

void Splay(int x, int g)
{
    while (fa[x] != g)
    {
        int f = fa[x];
        if (fa[f] == g)
        {
            Rotate(x);
            break;
        }
        if (which(x) ^ which(f))
            Rotate(x);
        else
            Rotate(f);
        Rotate(x);
    }
    if (!g) root = x;
}

int build(int l, int r, int rt) //创建一颗新的子树。
{
    if (l > r) return 0;
    int mid = (l + r) >> 1;
    int x = ++tot;
    fa[x] = rt; str[x] = S[mid];
    ch[x][0] = build(l, mid - 1, x);
    ch[x][1] = build(mid + 1, r, x);
    push_up(x);
    return x;
}

int main(){
    #ifdef LOCAL_DEFINE
        freopen("rush_in.txt", "r", stdin);
    #endif
    ios::sync_with_stdio(0),cin.tie(0);

    root = 1;
    tot++;str[tot] = '@';siz[tot] = 2;ch[tot][1] = tot+1;

    tot++;str[tot] = '#';siz[tot] = 1;fa[tot] = 1;
    //创建两个边界节点。

    cin >> n;
    while (n--){
        cin >> s;
        //cout<<s<<endl;
        if (s[0]=='M'){
            int k;
            cin >> k;
            pos = k;
        }else if (s[0]=='P'){
            pos--;
        }else if (s[0]=='N'){
            pos++;
        }else if (s[0]=='I'){
            int len;
            cin >> len;cin.get();
            cin.getline(S,N);
            int x = Rank(root,pos+1),y = Rank(root,pos+1+1);
            Splay(x,0);Splay(y,x);
            ch[y][0] = build(0,len-1,y);
            push_up(y);push_up(x);
            Splay(y,0);
        }else if (s[0]=='D'){
            int len;
            cin >> len;
            int x = Rank(root,pos+1),y = Rank(root,pos+1+len+1);
            Splay(x,0);Splay(y,x);
            ch[y][0] = 0;
            push_up(y);push_up(x);
            Splay(y,0);
        }else if (s[0]=='R'){
            int len;
            cin >> len;
            int x = Rank(root,pos+1),y = Rank(root,pos+1+len+1);
            Splay(x,0);Splay(y,x);
            int t = ch[y][0];
            tag[t] ^= 1;
        }else if (s[0]=='G'){
            int x = Rank(root,pos+2);
            cout<<str[x]<<endl;
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/AWCXV/p/8904087.html

时间: 2024-11-06 07:14:28

【BZOJ 1269】 [AHOI2006]文本编辑器editor的相关文章

BZOJ 1269: [AHOI2006]文本编辑器editor( splay )

splay..( BZOJ 1507 题目基本相同..双倍经验 ) ----------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define rep( i , n ) for( int i = 0 ; i <

bzoj 1269 [AHOI2006]文本编辑器editor

原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1269 伸展树的运用,如下: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using std::swap; 7 const int Max_N = 3000010; 8 stru

1269: [AHOI2006]文本编辑器editor

1269: [AHOI2006]文本编辑器editor Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4718  Solved: 1807[Submit][Status][Discuss] Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:   文本:由0个或多个字符构成的序列.这些字符的ASCII码在闭区间[32,

AHOI2006文本编辑器editor

1269: [AHOI2006]文本编辑器editor Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1885  Solved: 683[Submit][Status] Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:   文本:由0个或多个字符构成的序列.这些字符的ASCII码在闭区间[32, 126]内,也就是说

【BZOJ1269】[AHOI2006]文本编辑器editor Splay

[BZOJ1269][AHOI2006]文本编辑器editor Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对"文本编辑器"做了一个抽象的定义:   文本:由0个或多个字符构成的序列.这些字符的ASCII码在闭区间[32, 126]内,也就是说,这些字符均为可见字符或空格.光标:在一段文本中用于指示位置的标记,可以位于文本的第一个字符之前,文本的最后一个字符之后或文本的某两个相邻字符之间

[AHOI2006]文本编辑器editor

一不小心又开启了每天昏迷24个小时的状态,脑子不清醒的时候就该去看动画片. 只需要记录光标的位置即可,剩下的就是Splay的经典操作了,不多说了,我只是为了测试模板. #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath>

[AHOI2006]文本编辑器editor (Splay tree)

我感觉伸展树越来越模版了,没想到这么轻易的就过了... 把光标位置标记为pos MOVE:pos++或者pos-- INSERT:把光标旋转至根部,然后把光标后一个字母旋转至根的右子树,然后把insert的内容插入到root的右子树的左子树 ROTATE:把光标旋转至根部,然后把光标后一个字母旋转至根的右子树,然后把rev[root10]取反 GET:得到光标位置的后继,可以GET_KTH后然后GET_NEXT,也可以直接旋转,或者旋转后GET_MIN PREV,NEXT:都只需要改变光标位置变

[bzoj1269][AHOI2006文本编辑器editor] (splay模版题)

Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:   文本:由0个或多个字符构成的序列.这些字符的ASCII码在闭区间[32, 126]内,也就是说,这些字符均为可见字符或空格.光标:在一段文本中用于指示位置的标记,可以位于文本的第一个字符之前,文本的最后一个字符之后或文本的某两个相邻字符之间.文本编辑器:为一个可以对一段文本和该文本中的一个光标进行如下七条操作的程

【rope】bzoj1269 [AHOI2006]文本编辑器editor

维护一个字符串,支持以下操作: 主要就是 成段插入.成段删除.成段翻转.前两个操作很好通过rope实现.第三个操作也不难,维护两个rope,一个正向,一个反向,翻转时swap一下就行了. rope教程: http://blog.csdn.net/iamzky/article/details/38348653 Code(Orz zky): 1 #include<cstdio> 2 #include<ext/rope> 3 using namespace std; 4 using na