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;
    }
    
    
  • 相关阅读:
    数据绑定表达式语法(Eval,Bind区别)
    使用博客园的第一件事 自定义主题
    sql2000 跨服务器复制表数据
    使用UpdatePanel 局部刷新出现中文乱码的解决方法!!
    MMC不能打开文件MSC文件
    sql 日期 、时间相关
    loaded AS2 swf call function in AS3 holder
    Rewrite the master page form action attribute in asp.net 2.0
    100万个不重复的8位的随机数
    flash 中实现斜切变型
  • 原文地址:https://www.cnblogs.com/AWCXV/p/8904087.html
Copyright © 2011-2022 走看看