• P3391 文艺平衡树


    P3391 文艺平衡树

    题目描述

    维护序列, 有若干翻转操作, 输出最后序列


    Solution

    带翻转标记的平衡树模板
    在翻转时, 查询第L-1大, 和R+1大的元素 (此时下标为权值)
    ( 考虑到交换左右子树对查找树性质的影响, 所以不能直接查询前驱后继 )
    rotaterotate操作, 和查询kk大操作下传标记即可
    因为每个元素固定只有一个, 所以不用开cnt数组
    输出时直接输出中序遍历即可


    Code

    
    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 100005;
    
    int N, M, node_num, rot;
    int ch[maxn][2];
    int key[maxn], par[maxn], tag[maxn], size[maxn];
    
    inline int chk(int x){ return ch[par[x]][1] == x; }
    
    void push_down(int k){
            tag[k] = 0;
            std::swap(ch[k][0], ch[k][1]);
            tag[ch[k][0]] ^= 1, tag[ch[k][1]] ^= 1;
    }
    
    inline void push_up(int k){ size[k] = size[ch[k][0]] + size[ch[k][1]] + 1; }
    
    void rotate(int x){
            int fa = par[x], gra = par[fa], son = ch[x][chk(x)^1], dir = chk(x);
            if(tag[fa]) push_down(fa);
            if(tag[x]) push_down(x);
            ch[fa][dir] = son,  par[son] = fa;
            ch[gra][chk(fa)] = x, par[x] = gra;
            ch[x][dir^1] = fa, par[fa] = x;
            push_up(fa), push_up(x);
    }
    
    void Splay(int x, int aim = 0){
            while(par[x] != aim){
                    int fa = par[x], gra = par[fa];
                    if(gra != aim){                                 //sign
                            if(chk(x) == chk(fa)) rotate(fa);
                            else rotate(x);
                    }
                    rotate(x);
            }
            if(!aim) rot = x;
    }
    
    void Insert(int x){
            int cur = rot, last = 0;
            while(cur) last = cur, cur = ch[cur][key[cur]<x];
            cur = ++ node_num;
            if(last) ch[last][key[last]<x] = cur;                   //sign
            ch[cur][0] = ch[cur][1] = 0; 
            key[cur] = x, par[cur] = last;
            size[cur] = 1;
            Splay(cur);
    }
    
    void find(int x){
            if(!rot) return ;
            int cur = rot;
            while(ch[cur][key[cur]<x] && key[cur] != x) cur = ch[cur][key[cur]<x];
            Splay(cur);                                             //sign
    }
    
    int S_pre(int x, short opt){
            find(x);
            int cur = ch[rot][opt]; opt ^= 1;
            while(ch[cur][opt]) cur = ch[cur][opt];
            return cur;
    }
    
    int Kth(int k, int tmp){
            if(tag[k]) push_down(k);
            if(size[ch[k][0]] >= tmp) return Kth(ch[k][0], tmp);
            if(tmp > size[ch[k][0]] + 1){
                   tmp -= size[ch[k][0]] + 1;
                   return Kth(ch[k][1], tmp);
            }
            return k;
    }
    
    void Reverse(int l, int r){
    //        int L = S_pre(l, 0), R = S_pre(r, 1);
            int L = Kth(rot, l), R = Kth(rot, r+2);
    //        printf("L: %d R: %d
    ", key[L], key[R]);
            Splay(L), Splay(R, L);
            int k = ch[R][0];
            tag[k] ^= 1;
    }
    
    void print(int k){
            if(!k) return ;
            if(tag[k]) push_down(k);
            print(ch[k][0]);
            if(key[k] >= 1 && key[k] <= N) printf("%d ", key[k]);
            print(ch[k][1]);
    }
    
    int main(){
            scanf("%d%d", &N, &M);
            Insert(N+1), Insert(0);
            for(reg int i = 1; i <= N; i ++) Insert(i);
            int L, R;
     //       printf("%d
    ", size[rot]);
            while(M --){
                    scanf("%d%d", &L, &R);
                    Reverse(L, R);
            }
            print(rot);
            return 0;
    }
    
  • 相关阅读:
    又见斐波那契 矩阵快速幂 线性代数 转移矩阵构造
    Sticks POJ
    四则运算表达式求值——中缀表达式转后缀及计算
    D. Who killed Cock Robin 湖北省大学程序设计竞赛
    B. Salty Fish Go! -期望题(瞎搞题)
    A. Srdce and Triangle 几何题
    H. GSS and Simple Math Problem 高精度乘法模板
    小国的复仇 想法题/数学题附数论模板
    【作业】用栈模拟dfs
    KMP算法
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822678.html
Copyright © 2020-2023  润新知