1. 程式人生 > >【模板】文藝平衡樹(Splay)

【模板】文藝平衡樹(Splay)

rev 有序 base blog 其中 OS return 操作 i++

題目背景

這是一道經典的Splay模板題——文藝平衡樹。

題目描述

您需要寫一種數據結構(可參考題目標題),來維護一個有序數列,其中需要提供以下操作:翻轉一個區間,例如原有序序列是5 4 3 2 1,翻轉區間是[2,4]的話,結果是5 2 3 4 1

輸入輸出格式

輸入格式:

第一行為n,m n表示初始序列有n個數,這個序列依次是(1,2, \cdots n-1,n)(1,2,?n?1,n) m表示翻轉操作次數

接下來m行每行兩個數 [l,r][l,r] 數據保證 1 \leq l \leq r \leq n1lrn

輸出格式:

輸出一行n個數字,表示原始序列經過m次變換後的結果

#include <bits/stdc++.h>

using namespace std;
const int maxn = 100000+5;
const int inf = 2000000008;
int root,tot,ch[maxn][2],lazy[maxn],fa[maxn],siz[maxn];
int n,m;
struct Splay{
    void init(int t, int par = 0){
        ch[t][0] = ch[t][1] = 0; fa[t] = par;
    }
    void up(int t){
        siz[t] = siz[ch[t][1
]] + siz[ch[t][0]] + 1; } void down(int t){ if(!lazy[t])return; swap(ch[t][0], ch[t][1]); lazy[ch[t][0]] ^= 1; lazy[ch[t][1]] ^= 1; lazy[t] = 0; } void init(){ init(0, 0); tot = root = 0; } int find( int x, int t = root){ down(t);
if(!x)return t; if(x > siz[ch[t][0]]+1)return find(x - siz[ch[t][0]] - 1, ch[t][1]); if(x == siz[ch[t][0]] + 1)return t; return find(x, ch[t][0]); } void rotate(int x, int d){ int y = fa[x]; down(y),down(x); ch[y][d^1] = ch[x][d]; if(ch[x][d])fa[ch[x][d]] = y; fa[x] = fa[y]; if(fa[y]){ if(y == ch[fa[y]][d])ch[fa[y]][d] = x; else ch[fa[y]][d^1] = x; } ch[x][d] = y;fa[y] = x; up(y),up(x); } void splay(int x, int targrt){ while(fa[x] != targrt){ int y = fa[x]; if(x == ch[y][0]){ if(targrt != fa[y]&& y == ch[fa[y]][0]) rotate(y, 1); rotate(x, 1); } else { if(targrt != fa[y]&& y == ch[fa[y]][1]) rotate(y, 0); rotate(x, 0); } } if(!targrt)root = x; } int build(int f, int l, int r){ if(l > r)return 0; int m = (l + r) >> 1; init(m, f); ch[m][0] = build(m, l, m-1); ch[m][1] = build(m, m+1, r); up(m); return m; } void rev(int l, int r){ int L = find(l); int R = find(r+2); splay(L, 0); splay(R, L); //int x = ch[R][0]; int x = ch[ch[root][1]][0]; lazy[x] ^= 1; } }Tr; int main() { scanf("%d%d",&n,&m); root = Tr.build(0, 1, n+2); while(m--){ int opt,x; scanf("%d%d",&opt,&x); Tr.rev(opt, x); } for(int i = 1; i <= n; i++)printf("%d ",Tr.find(i+1)-1); return 0; }

【模板】文藝平衡樹(Splay)