zoukankan      html  css  js  c++  java
  • 【BZOJ 1269】 [AHOI2006]文本编辑器editor

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

    在这里输入题意

    【题解】

    ```cpp /* 【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了。
    
    </font>
    
    <font color = black size = 6> 【代码】</font>
    ```cpp
    #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;
    }
    
    
  • 相关阅读:
    SQL Server 创建用户报错:消息 15023,级别 16,状态 1,第 1 行 用户、组或角色 'XXX' 在当前数据库中已存在。
    Win10安装sqlserver2014打开显示黑色界面,mardown打开显示报错
    Centos7磁盘超过2TB使用parted命令分区
    Html5學習重點清單
    jQuery源码学习扒一扒jQuery对象初使化
    jQuery源码学习
    算法排序之插入排序
    算法排序之冒泡排序
    Sublime Text 3 安装
    css布局你该了解的
  • 原文地址:https://www.cnblogs.com/AWCXV/p/8904087.html
Copyright © 2011-2022 走看看