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\n", 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\n", size[rot]);
        while(M --){
                scanf("%d%d", &L, &R);
                Reverse(L, R);
        }
        print(rot);
        return 0;
}
posted @ 2019-03-17 14:50  XXX_Zbr  阅读(77)  评论(0编辑  收藏  举报