P3391 【模板】文艺平衡树

Splay 区间翻转,存个代码

旋转时,要注意goal是引用 , 并记得修改 , 有标记的一定记得标记下放 , 还有清空

#include
#include
using namespace std;
const int N = 101000;
inline int read()
{
    register int x = 0 , f = 0; register char c = getchar();
    while(c < '0' || c > '9') f |= c == '-' , c = getchar();
    while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
    return f ? -x : x;
}
#define RQ puts("RQ");
int n , m , sz , root;
int tr[N][2] , val[N] , rev[N] , fa[N] , siz[N];
inline int Newnode() { return ++sz; }
inline void update(int x) { siz[x] = siz[tr[x][0]] + siz[tr[x][1]] + 1; }
inline int witch(int x) { return x == tr[fa[x]][1]; }
inline int rk(int x) { return 1 + siz[tr[x][0]]; }
void rot(int x , int &goal) // 忘记了修改 goal 
{
    int y = fa[x] , z = fa[y] , k = witch(x) , w = tr[x][!k];
    if(y == goal) goal = x; else tr[z][witch(y)] = x; 
    fa[x] = z; tr[y][k] = w; if(w) fa[w] = y;
    tr[x][!k] = y; fa[y] = x;
    update(y); update(x);
}

void down(int x)
{
    if(!x || !rev[x]) return ; // 没用判断标记 
    swap(tr[x][0] , tr[x][1]);
    if(tr[x][0]) rev[tr[x][0]] ^= 1;
    if(tr[x][1]) rev[tr[x][1]] ^= 1;
    rev[x] = 0; // 还没有清空 
    return ;
}

void Splay(int x , int &goal) // 引用 
{
    while(x != goal)
    {
        if(fa[x] != goal) rot(witch(x) == witch(fa[x]) ? fa[x] : x , goal);
        rot(x , goal);
    }
    return ;
}

void build(int &k , int l , int r , int f)
{
    if(l > r) return ; int mid = (l + r) >> 1;
    if(!k) k = Newnode(); siz[k] = 1; fa[k] = f; val[k] = mid;
    build(tr[k][0] , l , mid - 1 , k);
    build(tr[k][1] , mid + 1 , r , k);
    update(k); return ;
}

int kth(int k) // 求的是第k大的是谁 , 而不是k的排名 
{
    int p = root;
    while(down(p) , rk(p) != k)
    {
        if(rk(p) < k) k -= rk(p) , p = tr[p][1];
        else p = tr[p][0];
    }
    Splay(p , root);
    return p;
}

void reverse(int l , int r)
{
    int x = kth(l) , y = kth(r);
    Splay(x , root); Splay(y , tr[x][1]);
    rev[tr[y][0]] ^= 1; return ;
}

void dfs(int x)
{
    if(!x) return ; down(x);
    dfs(tr[x][0]);
    if(val[x] >= 1 && val[x] <= n) printf("%d " , val[x]);
    dfs(tr[x][1]);
    return ;
}

int main()
{
    n = read(); m = read();
    build(root , 0 , n+1 , 0);
    for(int i = 1 ; i <= m ; ++i)
    {
        int l = read() , r = read();
        reverse(l , r + 2);
    }
    dfs(root);
    return 0;
}

你可能感兴趣的:(P3391 【模板】文艺平衡树)