算法笔记--Splay && Link-Cut-Tree && fhq _treap

Splay

参考:https://tiger0132.blog.luogu.org/slay-notes

普通模板:

const int N = 1e5 + 10;
int ch[N][2], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = 0, rt = 0;
int n, m;
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
///区间反转
inline void push_down(int x) {
    if(lazy[x]) {
        swap(ch[x][0], ch[x][1]);
        lazy[ch[x][0]] ^= 1;
        lazy[ch[x][1]] ^= 1;
        lazy[x] = 0;
    }
}
void Rotate(int x) {
    int y = fa[x], z = fa[y];
    push_down(y), push_down(x);///区间反转
    int k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    push_down(x);///区间反转
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
void Find(int x) {
    if(!rt) return ;
    int cur = rt;
    while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]];
    Splay(cur);
}
void Insert(int x) {
    int cur = rt, p = 0;
    while(cur && val[cur] != x) {
        p = cur;
        cur = ch[cur][x>val[cur]];
    }
    if(cur) cnt[cur]++;
    else {
        cur = ++ncnt;
        if(p) ch[p][x>val[p]] = cur;
        fa[cur] = p;
        ch[cur][0] = ch[cur][1] = 0;
        val[cur] = x;
        cnt[cur] = sz[cur] = 1;
    }
    Splay(cur);
}
int Kth(int k) {
    int cur = rt;
    while(true) {
        push_down(cur); ///区间反转
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return cur;
    }
}
inline int get_min(int x) {
    while(x && ch[x][0]) x = ch[x][0];
    return x;
}
inline int get_max(int x) {
    while(x && ch[x][1]) x = ch[x][1];
    return x;
}
int Pre(int x) {
    Find(x);
    if(val[rt] < x) return rt;
    int cur = ch[rt][0];
    while(ch[cur][1]) cur = ch[cur][1];
    return cur;
}
int Succ(int x) {
    Find(x);
    if(val[rt] > x) return rt;
    int cur = ch[rt][1];
    while(ch[cur][0]) cur = ch[cur][0];
    return cur;
}
void Remove(int x) {
    int last = Pre(x), next = Succ(x);
    Splay(last), Splay(next, last);
    int del = ch[next][0];
    if(cnt[del] > 1) cnt[del]--, Splay(del);
    else ch[next][0] = 0, push_up(next), push_up(last);
}
///区间反转
void Reverse(int l, int r) {
    int x = Kth(l), y = Kth(r+2);
    Splay(x), Splay(y, x);
    lazy[ch[y][0]] ^= 1;
}
void Output(int x) {
    push_down(x);
    if(ch[x][0]) Output(ch[x][0]);
    if(1 <= val[x] && val[x] <= n) printf("%d ", val[x]);
    if(ch[x][1]) Output(ch[x][1]);
}
void delete_root() {
    if(ch[rt][1]) {
        int cur = ch[rt][1];
        while(cur && ch[cur][0]) cur = ch[cur][0];
        Splay(cur, rt);
        ch[cur][0] = ch[rt][0];
        fa[ch[cur][0]] = cur;
        rt = cur;
    }
    else rt = ch[rt][0];
    fa[rt] = 0;
    if(rt) push_up(rt);
}
inline int NewNode(int x) {
    int cur;
    if(q.empty()) cur = ++ncnt;
    else cur = q.front(), q.pop();
    ///初始化
    ch[cur][0] = ch[cur][1] = fa[cur] = lazy[cur] = 0;
    val[cur] = x;
    sz[cur] = cnt[cur] = 1;
    return cur;
}
void Recycle(int x) {
    if(ch[x][0]) Recycle(ch[x][0]);
    if(ch[x][1]) Recycle(ch[x][1]);
    if(x) q.push(x);
}
int build(int l, int r, int *a) {
    if(l > r) return 0;
    int mid = l+r >> 1, cur = NewNode(a[mid]);
    if(l == r) return cur;
    if(ch[cur][0] = build(l, mid-1, a)) fa[ch[cur][0]] = cur;
    if(ch[cur][1] = build(mid+1, r, a)) fa[ch[cur][1]] = cur;
    push_up(cur);
    return cur;
}
inline void init() {
    ncnt = rt = ch[0][0] = ch[0][1] = fa[0] = sz[0] = cnt[0] = val[0] = lazy[0] = 0;
}

按排名插入模板(常数较小???也许以前的方法写搓了):

inline void Newnode(int &cur, int f, int a) {
    cur = ++ncnt;
    fa[cur] = f;
    val[cur] = a;
    ch[cur][0] = ch[cur][1] = 0;
    sz[cur] = cnt[cur] = 1;
}
void Insert(int x, int y) {
    int p = 0;
    if(!rt) {
        Newnode(rt, 0, y);
        return ;
    }
    if(!x) {
        p = rt;
        sz[p]++;
        while(ch[p][0]) p = ch[p][0], sz[p]++;
        Newnode(ch[p][0], p, y);
        Splay(ch[p][0]);
        return ;
    }
    int u = Kth(x);
    Splay(u);
    Newnode(rt, 0, y);
    ch[rt][1] = ch[u][1];
    fa[ch[rt][1]] = rt;
    ch[u][1] = 0;
    ch[rt][0] = u;
    fa[u] = rt;
    push_up(u), push_up(rt);
}

例题:

P3369 【模板】普通平衡树 

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 2e5 + 10;
int ch[N][2], val[N], cnt[N], fa[N], sz[N], ncnt = 0, rt = 0;
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
void Rotate(int x) {
    int y = fa[x], z = fa[y], k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
void Find(int x) {
    if(!rt) return ;
    int cur = rt;
    while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]];
    Splay(cur);
}
void Insert(int x) {
    int cur = rt, p = 0;
    while(cur && val[cur] != x) {
        p = cur;
        cur = ch[cur][x>val[cur]];
    }
    if(cur) cnt[cur]++;
    else {
        cur = ++ncnt;
        if(p) ch[p][x>val[p]] = cur;
        fa[cur] = p;
        ch[cur][0] = ch[cur][1] = 0;
        val[cur] = x;
        cnt[cur] = sz[cur] = 1;
    }
    Splay(cur);
}
int Kth(int k) {
    int cur = rt;
    while(true) {
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return cur;
    }
}
int Pre(int x) {
    Find(x);
    if(val[rt] < x) return rt;
    int cur = ch[rt][0];
    while(ch[cur][1]) cur = ch[cur][1];
    return cur;
}
int Succ(int x) {
    Find(x);
    if(val[rt] > x) return rt;
    int cur = ch[rt][1];
    while(ch[cur][0]) cur = ch[cur][0];
    return cur;
}
void Remove(int x) {
    int last = Pre(x), next = Succ(x);
    Splay(last), Splay(next, last);
    int del = ch[next][0];
    if(cnt[del] > 1) cnt[del]--, Splay(del);
    else ch[next][0] = 0/*, push_up(next), push_up(last)*/;
}
int n, opt, x;
int main() {
    Insert(INT_MIN);
    Insert(INT_MAX);
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d %d", &opt, &x);
        if(opt == 1) Insert(x);
        else if(opt == 2) Remove(x);
        else if(opt == 3) Find(x), printf("%d
", sz[ch[rt][0]]);
        else if(opt == 4) printf("%d
", val[Kth(x+1)]);
        else if(opt == 5) printf("%d
", val[Pre(x)]);
        else printf("%d
", val[Succ(x)]);
    }
    return 0;
}
View Code

P3391 【模板】文艺平衡树(Splay) 

思路:跟区间反转相关的Splay维护的都是下标

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 10;
int ch[N][2], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = 0, rt = 0;
int n, m;
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
///区间反转
inline void push_down(int x) {
    if(lazy[x]) {
        swap(ch[x][0], ch[x][1]);
        lazy[ch[x][0]] ^= 1;
        lazy[ch[x][1]] ^= 1;
        lazy[x] = 0;
    }
}
void Rotate(int x) {
    int y = fa[x], z = fa[y], k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
void Find(int x) {
    if(!rt) return ;
    int cur = rt;
    while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]];
    Splay(cur);
}
void Insert(int x) {
    int cur = rt, p = 0;
    while(cur && val[cur] != x) {
        p = cur;
        cur = ch[cur][x>val[cur]];
    }
    if(cur) cnt[cur]++;
    else {
        cur = ++ncnt;
        if(p) ch[p][x>val[p]] = cur;
        fa[cur] = p;
        ch[cur][0] = ch[cur][1] = 0;
        val[cur] = x;
        cnt[cur] = sz[cur] = 1;
    }
    Splay(cur);
}
int Kth(int k) {
    int cur = rt;
    while(true) {
        push_down(cur); ///区间反转
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return cur;
    }
}
int Pre(int x) {
    Find(x);
    if(val[rt] < x) return rt;
    int cur = ch[rt][0];
    while(ch[cur][1]) cur = ch[cur][1];
    return cur;
}
int Succ(int x) {
    Find(x);
    if(val[rt] > x) return rt;
    int cur = ch[rt][1];
    while(ch[cur][0]) cur = ch[cur][0];
    return cur;
}
void Remove(int x) {
    int last = Pre(x), next = Succ(x);
    Splay(last), Splay(next, last);
    int del = ch[next][0];
    if(cnt[del] > 1) cnt[del]--, Splay(del);
    else ch[next][0] = 0, push_up(next), push_up(last);
}
///区间反转
void Reverse(int l, int r) {
    int x = Kth(l), y = Kth(r+2);
    Splay(x), Splay(y, x);
    lazy[ch[y][0]] ^= 1;
}
void Output(int x) {
    push_down(x);
    if(ch[x][0]) Output(ch[x][0]);
    if(1 <= val[x] && val[x] <= n) printf("%d ", val[x]);
    if(ch[x][1]) Output(ch[x][1]);
}
int l, r;
int main() {
    scanf("%d %d", &n, &m);
    for (int i = 0; i <= n+1; ++i) Insert(i);
    while(m--) {
        scanf("%d %d", &l, &r);
        Reverse(l, r);
    }
    Output(rt);
    return 0;
}
View Code

P2042 [NOI2005]维护数列 

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e6 + 10;
int ch[N][2], val[N], cnt[N], fa[N], sz[N], rev[N], lazy[N], ncnt = 0, rt = 0;
int n, m, a[N], lmx[N], rmx[N], mx[N], sm[N];
queue<int> q;
inline int NewNode(int x) {
    int cur;
    if(q.empty()) cur = ++ncnt;
    else cur = q.front(), q.pop();
    ch[cur][0] = ch[cur][1] = fa[cur] = 0;
    rev[cur] = lazy[cur] = 0;
    sz[cur] = cnt[cur] = 1;
    mx[cur] = sm[cur] = val[cur] = x;
    lmx[cur] = rmx[cur] = max(0, x);
    return cur;
}
void Recycle(int x) {
    if(ch[x][0]) Recycle(ch[x][0]);
    if(ch[x][1]) Recycle(ch[x][1]);
    if(x) q.push(x);
}
inline void push_up(int x) {
    int l = ch[x][0], r = ch[x][1];
    sz[x] = sz[l] + cnt[x] + sz[r];
    sm[x] = sm[l] + val[x] + sm[r];
    lmx[x] = max(lmx[l], sm[l] + val[x] + lmx[r]);
    rmx[x] = max(rmx[r], sm[r] + val[x] + rmx[l]);
    mx[x] = max(rmx[l] + val[x] + lmx[r], max(mx[l], mx[r]));
}
inline void push_down(int x) {
    int l = ch[x][0], r = ch[x][1];
    if(lazy[x]) {
        lazy[x] = rev[x] = 0;
        if(l) {
            lazy[l] = 1;
            val[l] = val[x];
            sm[l] = val[l] * sz[l];
            lmx[l] = rmx[l] = max(0, sm[l]);
            mx[l] = sm[l] > 0 ? sm[l] : val[l];
        }
        if(r) {
            lazy[r] = 1;
            val[r] = val[x];
            sm[r] = val[r] * sz[r];
            lmx[r] = rmx[r] = max(0, sm[r]);
            mx[r] = sm[r] > 0 ? sm[r] : val[r];
        }
    }
    if(rev[x]) {
        rev[l] ^= 1, rev[r] ^= 1, rev[x] = 0;
        swap(lmx[l], rmx[l]);
        swap(lmx[r], rmx[r]);
        swap(ch[l][0], ch[l][1]);
        swap(ch[r][0], ch[r][1]);
    }

}
int build(int l, int r, int *a) {
    if(l > r) return 0;
    int mid = l+r >> 1, cur = NewNode(a[mid]);
    if(l == r) return cur;
    if(ch[cur][0] = build(l, mid-1, a)) fa[ch[cur][0]] = cur;
    if(ch[cur][1] = build(mid+1, r, a)) fa[ch[cur][1]] = cur;
    push_up(cur);
    return cur;
}
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
void Rotate(int x) {
    int y = fa[x], z = fa[y], k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
int Kth(int k) {
    int cur = rt;
    while(true) {
        push_down(cur); ///区间反转
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return cur;
    }
}
///区间反转
void Reverse(int x, int y) {
    int u = Kth(x), v = Kth(x+y+1);
    Splay(u), Splay(v, u);
    int son = ch[v][0];
    if(!lazy[son]) {
        rev[son] ^= 1;
        swap(ch[son][0], ch[son][1]);
        swap(lmx[son], rmx[son]);
    }
    push_up(v), push_up(u);
}
void Insert(int x, int y) {
    for (int i = 1; i <= y; ++i) scanf("%d", &a[i]);
    int u = Kth(x+1), v = Kth(x+2);
    Splay(u), Splay(v, u);
    int cur = build(1, y, a);
    ch[v][0] = cur, fa[cur] = v;
    push_up(v), push_up(u);
}
void Delete(int x, int y) {
    int u = Kth(x), v = Kth(x+y+1);
    Splay(u), Splay(v, u);
    Recycle(ch[v][0]);
    ch[v][0] = 0;
    push_up(v), push_up(u);
}
void Make_Same(int x, int y, int z) {
    int u = Kth(x), v = Kth(x+y+1);
    Splay(u), Splay(v, u);
    int son = ch[v][0];
    lazy[son] = 1;
    val[son] = z;
    sm[son] = z*sz[son];
    mx[son] = sm[son] > 0 ? sm[son] : val[son];
    lmx[son] = rmx[son] = max(0, sm[son]);
    push_up(v), push_up(u);
}
int Get_Sum(int x, int y) {
    int u = Kth(x), v = Kth(x+y+1);
    Splay(u), Splay(v, u);
    push_up(v), push_up(u);
    return sm[ch[v][0]];
}
char opt[20];
int x, y, z;
int main() {
    scanf("%d %d", &n, &m);
    for (int i = 2; i <= n+1; ++i) scanf("%d", &a[i]);
    a[1] = a[n+2] = mx[0] = -2000;
    rt = build(1, n+2, a);
    for (int i = 0; i < m; ++i) {
        scanf("%s", opt);
        if(opt[0] == 'I') {
            scanf("%d %d", &x, &y);
            Insert(x, y);
        }
        else if(opt[0] == 'D') {
            scanf("%d %d", &x, &y);
            Delete(x, y);
        }
        else if(opt[0] == 'M' && opt[5] == 'S') {
            scanf("%d %d %d", &x, &y, &z);
            Make_Same(x, y, z);
        }
        else if(opt[0] == 'R') {
            scanf("%d %d", &x, &y);
            Reverse(x, y);
        }
        else if(opt[0] == 'G') {
            scanf("%d %d", &x, &y);
            printf("%d
", Get_Sum(x, y));
        }
        else printf("%d
", mx[rt]);
    }
    return 0;
}
View Code

POJ 3481

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<cstdio>
#include<iostream>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";

const int N = 1e6 + 10;
int ch[N][2], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = 0, rt = 0;
int a[N];
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
void Rotate(int x) {
    int y = fa[x], z = fa[y], k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
void Find(int x) {
    if(!rt) return ;
    int cur = rt;
    while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]];
    Splay(cur);
}
void Insert(int x, int id) {
    int cur = rt, p = 0;
    while(cur && val[cur] != x) {
        p = cur;
        cur = ch[cur][x>val[cur]];
    }
    if(cur) cnt[cur]++;
    else {
        cur = ++ncnt;
        if(p) ch[p][x>val[p]] = cur;
        fa[cur] = p;
        ch[cur][0] = ch[cur][1] = 0;
        val[cur] = x;
        a[cur] = id;
        cnt[cur] = sz[cur] = 1;
    }
    Splay(cur);
}
int Kth(int k) {
    int cur = rt;
    while(true) {
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return cur;
    }
}
int Pre(int x) {
    Find(x);
    if(val[rt] < x) return rt;
    int cur = ch[rt][0];
    while(ch[cur][1]) cur = ch[cur][1];
    return cur;
}
int Succ(int x) {
    Find(x);
    if(val[rt] > x) return rt;
    int cur = ch[rt][1];
    while(ch[cur][0]) cur = ch[cur][0];
    return cur;
}
void Remove(int x) {
    int last = Pre(x), next = Succ(x);
    Splay(last), Splay(next, last);
    int del = ch[next][0];
    if(cnt[del] > 1) cnt[del]--, Splay(del);
    else ch[next][0] = 0, push_up(next), push_up(last);
}
int ty, k, p;
int main() {
    int now = 0;
    Insert(-100, 0);
    Insert(10000010, 0);
    while(~scanf("%d", &ty) && ty) {
        if(ty == 1) {
            scanf("%d %d", &k, &p);
            Insert(p, k);
            ++now;
        }
        else if(ty == 2) {
            if(!now) {
                printf("0
");
                continue;
            }
            int cur = Kth(now+1);
            printf("%d
", a[cur]);
            --now;
            Remove(val[cur]);
        }
        else if(ty == 3) {
            if(!now) {
                printf("0
");
                continue;
            }
            int cur = Kth(2);
            printf("%d
", a[cur]);
            --now;
            Remove(val[cur]);
        }
    }
    return 0;
}
View Code

POJ 2828

Splay代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<iostream>
#include<cstdio>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 2e5 + 10;
int ch[N][2], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = 0, rt = 0;
int n, m, a[N];
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
void Rotate(int x) {
    int y = fa[x], z = fa[y], k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}

inline int Kth(int k) {
    int cur = rt;
    while(true) {
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return cur;
    }
}
inline void Newnode(int &cur, int f, int a) {
    cur = ++ncnt;
    fa[cur] = f;
    val[cur] = a;
    ch[cur][0] = ch[cur][1] = 0;
    sz[cur] = cnt[cur] = 1;
}
void Insert(int x, int y) {
    int p = 0;
    if(!rt) {
        Newnode(rt, 0, y);
        return ;
    }
    if(!x) {
        p = rt;
        sz[p]++;
        while(ch[p][0]) p = ch[p][0], sz[p]++;
        Newnode(ch[p][0], p, y);
        Splay(ch[p][0]);
        return ;
    }
    int u = Kth(x);
    Splay(u);
    Newnode(rt, 0, y);
    ch[rt][1] = ch[u][1];
    fa[ch[rt][1]] = rt;
    ch[u][1] = 0;
    ch[rt][0] = u;
    fa[u] = rt;
    push_up(u), push_up(rt);
}

void Output(int x) {
    if(ch[x][0]) Output(ch[x][0]);
    printf("%d ", val[x]);
    if(ch[x][1]) Output(ch[x][1]);
}
int x, y;
int main() {
   while(~scanf("%d", &n)) {
        ncnt = rt = 0;
        for (int i = 1; i <= n; ++i) {
            scanf("%d %d", &x, &y);
            Insert(x, y);
        }
        Output(rt);
        printf("
");
    }
    return 0;
}
View Code

树状数组代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 4e5 + 5;
int n, bit[N], res[N];
pii a[N];
void add(int x, int a) {
    while(x <= n) bit[x] += a, x += x&-x;
}
int Kth(int k) {
    int up = log(n)/log(2);
    int res = 0;
    for (int i = up; i >= 0; --i) {
        if(res + (1<<i) > n) continue;
        if(bit[res+(1<<i)] < k) {
            res += 1<<i;
            k -= bit[res];
        }
    }
    return res+1;
}
int main() {
    while(~scanf("%d", &n)) {
        for (int i = 1; i <= n; ++i) add(i, 1);
        for (int i = 1; i <= n; ++i) scanf("%d %d", &a[i].fi, &a[i].se);
        for (int i = n; i >= 1; --i) {
            int pos = Kth(a[i].fi+1);
            res[pos] = a[i].se;
            add(pos, -1);
        }
        for (int i = 1; i <= n; ++i) printf("%d%c", res[i], " 
"[i==n]);
        for (int i = 0; i <= n; ++i) bit[i] = 0;
    }
    return 0;
}
View Code

HDU 1890

思路:按下标建树,每次将要翻转到前面的节点Splay到根上,将它的左儿子打上标记,然后把根删掉。

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
int ch[N][2], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = 0, rt = 0;
int n, m, a[N], id[N], node[N], ans[N];
pii t[N];
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
///区间反转
inline void push_down(int x) {
    if(lazy[x]) {
        swap(ch[x][0], ch[x][1]);
        lazy[ch[x][0]] ^= 1;
        lazy[ch[x][1]] ^= 1;
        lazy[x] = 0;
    }
}
void Rotate(int x) {
    int y = fa[x], z = fa[y];
    push_down(y), push_down(x);
    int k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    push_down(x);
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
int Kth(int k) {
    int cur = rt;
    while(true) {
        push_down(cur); ///区间反转
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return cur;
    }
}

int Newnode(int x) {
    int cur = ++ncnt;
    ch[cur][0] = ch[cur][1] = fa[cur] = 0;
    val[cur] = x;
    cnt[cur] = sz[cur] = 1;
    lazy[cur] = 0;
    return cur;
}
int build(int l, int r, int *a) {
    if(l > r) return 0;
    int mid = l+r >> 1, cur = Newnode(a[mid]);
    node[id[mid]] = cur;
    if(l == r) return cur;
    if(ch[cur][0] = build(l, mid-1, a)) fa[ch[cur][0]] = cur;
    if(ch[cur][1] = build(mid+1, r, a)) fa[ch[cur][1]] = cur;
    push_up(cur);
    return cur;
}
void delete_root() {
    int old = rt;
    if(ch[rt][1]) {
        rt = ch[rt][1];
        Splay(Kth(1));
        ch[rt][0] = ch[old][0];
        fa[ch[rt][0]] = rt;
    }
    else rt = ch[rt][0];
    fa[rt] = 0;
    push_up(rt);
}
int main() {
    while(~scanf("%d", &n)) {
        if(n == 0) break;
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
            t[i].fi = a[i];
            t[i].se = i;
        }
        sort(t+1, t+1+n);
        for (int i = 1; i <= n; ++i) id[t[i].se] = i;
        rt = ncnt = 0;
        sz[0] = cnt[0] = ch[0][0] = ch[0][1] = fa[0] = lazy[0] = 0;
        rt = build(1, n, a);
        for (int i = 1; i <= n; ++i) {
            Splay(node[i]);
            printf("%d%c", sz[ch[rt][0]]+i, " 
"[i==n]);
            lazy[ch[rt][0]] ^= 1;
            delete_root();
        }
    }
    return 0;
}
View Code

HDU 3436 

思路:先把TOP操作和QUERY操作的值单独扣出来,然后其他的一段区间看成一个节点

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<cstdio>
#include<iostream>
#include<vector>
#include<unordered_map>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 2e5 + 1000;
int ch[N][2], st[N], cnt[N], fa[N], sz[N], ncnt = 0, rt = 0;
int n, m;
int T, op[N/2], a[N/2], node[N], tot, vc[N/2], tmp;
pii t[N];
char s[100];
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
void Rotate(int x) {
    int y = fa[x], z = fa[y], k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
inline int Kth(int k) {
    int cur = rt;
    while(true) {
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return cur;
    }
}
inline int KTH(int k) {
    int cur = rt;
    while(true) {
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return st[cur] + k-sz[ch[cur][0]]-1;
    }
}
inline void delete_root() {
    if(ch[rt][1]) {
        int cur = ch[rt][1];
        while(cur && ch[cur][0]) cur = ch[cur][0];
        Splay(cur, rt);
        ch[cur][0] = ch[rt][0];
        fa[ch[cur][0]] = cur;
        rt = cur;
    }
    else rt = ch[rt][0];
    fa[rt] = 0;
    if(rt) push_up(rt);
}
inline int NewNode(pii x) {
    int cur = ++ncnt;
    ch[cur][0] = ch[cur][1] = fa[cur] = 0;
    st[cur] = x.fi;
    cnt[cur] = sz[cur] = x.se - x.fi + 1;
    return cur;
}
int build(int l, int r) {
    if(l > r) return 0;
    int mid = l+r >> 1, cur = NewNode(t[mid]);
    node[mid] = cur;
    if(l == r) return cur;
    ch[cur][0] = build(l, mid-1); if(ch[cur][0]) fa[ch[cur][0]] = cur;
    ch[cur][1] = build(mid+1, r); if(ch[cur][1]) fa[ch[cur][1]] = cur;
    push_up(cur);
    return cur;
}
inline int get(int x) {
    int l = 1, r = tot, m = l+r >> 1;
    while(l <= r) {
        if(t[m].fi > x) r = m-1;
        else if(t[m].se < x) l = m+1;
        else return node[m];
        m = l+r >> 1;
    }
}
inline void init() {
    tmp = 1;
    tot = 0;
    ncnt = rt = 0;
    ch[0][0] = ch[0][1] = st[0] = cnt[0] = fa[0] = sz[0] = 0;
}
int main() {
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    scanf("%d", &T);
    for (int cs = 1; cs <= T; ++cs) {
        init();
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= m; ++i) {
            scanf("%s%d", s, &a[i]);
            if(s[0] == 'T') op[i] = 1, vc[tmp++] = a[i];
            else if(s[0] == 'Q') op[i] = 2, vc[tmp++] = a[i];
            else op[i] = 3;
        }
        vc[tmp++] = n;
        sort(vc, vc+tmp);
        tmp = unique(vc, vc+tmp) - vc;
        for (int i = 1; i < tmp; ++i) {
            if(vc[i]-vc[i-1] > 1) t[++tot].fi = vc[i-1]+1, t[tot].se = vc[i]-1;
            t[++tot].fi = vc[i], t[tot].se = vc[i];
        }
        rt = build(1, tot);
        printf("Case %d:
", cs);
        for (int i = 1; i <= m; ++i) {
            if(op[i] == 1) {
                int cur = get(a[i]);
                Splay(cur);
                delete_root();
                int now = rt;
                while(now && ch[now][0]) now = ch[now][0];
                ch[now][0] = cur;
                fa[cur] = now;
                st[cur] = a[i];
                sz[cur] = cnt[cur] = 1;
                ch[cur][0] = ch[cur][1] = 0;
                Splay(cur);
            }
            else if(op[i] == 2) {
                int cur = get(a[i]);
                Splay(cur);
                printf("%d
", sz[ch[cur][0]]+1);
            }
            else printf("%d
", KTH(a[i]));
        }
    }
    return 0;
}
View Code

 HDU 3487

思路:常规操作

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 3e5 + 50;
int ch[N][2], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = 0, rt = 0;
int n, m;
int T, a[N], x, y, z, tmp;
char s[100];
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
///区间反转
inline void push_down(int x) {
    if(lazy[x]) {
        swap(ch[x][0], ch[x][1]);
        lazy[ch[x][0]] ^= 1;
        lazy[ch[x][1]] ^= 1;
        lazy[x] = 0;
    }
}
void Rotate(int x) {
    int y = fa[x], z = fa[y];
    push_down(y), push_down(x);///区间反转
    int k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    push_down(x);///区间反转
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
int Kth(int k) {
    int cur = rt;
    while(true) {
        push_down(cur); ///区间反转
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return cur;
    }
}
///区间反转
void Reverse(int l, int r) {
    int x = Kth(l), y = Kth(r+2);
    Splay(x), Splay(y, x);
    lazy[ch[y][0]] ^= 1;
}
void Cut(int l, int r, int c) {
    int x = Kth(l), y = Kth(r+2);
    Splay(x), Splay(y, x);
    int cur = ch[y][0];
    fa[cur] = 0;
    ch[y][0] = 0;
    x = Kth(c+1), y = Kth(c+2);
    Splay(x), Splay(y, x);
    fa[cur] = y;
    ch[y][0] = cur;
    Splay(cur);
}
void Output(int x) {
    push_down(x);
    if(ch[x][0]) Output(ch[x][0]);
    if(1 <= val[x] && val[x] <= n) printf("%d%c", val[x], " 
"[++tmp == n]);
    if(ch[x][1]) Output(ch[x][1]);
}
inline int NewNode(int x) {
    int cur = ++ncnt;
    ch[cur][0] = ch[cur][1] = fa[cur] = 0;
    val[cur] = x;
    sz[cur] = cnt[cur] = 1;
    lazy[cur] = 0;
    return cur;
}
int build(int l, int r, int *a) {
    if(l > r) return 0;
    int mid = l+r >> 1, cur = NewNode(a[mid]);
    if(l == r) return cur;
    if(ch[cur][0] = build(l, mid-1, a)) fa[ch[cur][0]] = cur;
    if(ch[cur][1] = build(mid+1, r, a)) fa[ch[cur][1]] = cur;
    push_up(cur);
    return cur;
}

int main() {
    for (int i = 0; i < N; ++i) a[i] = i;
    while(~scanf("%d %d", &n, &m)) {
        if(n == -1 && m == -1) break;
        rt = ncnt = ch[0][0] = ch[1][0] = fa[0] = sz[0] = cnt[0] = lazy[0] = 0;
        rt = build(0, n+1, a);
        for (int i = 1; i <= m; ++i) {
            scanf("%s", s);
            if(s[0] == 'C') {
                scanf("%d %d %d", &x, &y, &z);
                Cut(x, y, z);
            }
            else {
                scanf("%d %d", &x, &y);
                Reverse(x, y);
            }
        }
        tmp = 0;
        Output(rt);
    }
    return 0;
}
View Code

 HYSBZ 1208

思路:平衡树

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<climits>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 10;
const int MOD = 1e6;
struct splay {
    int ch[N][2], cnt[N], fa[N], sz[N], ncnt, rt;
    int n, m;
    LL val[N];
    inline int ck(int x) {
        return ch[fa[x]][1] == x;
    }
    inline void push_up(int x) {
        sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
    }
    void Rotate(int x) {
        int y = fa[x], z = fa[y];
        int k = ck(x), w = ch[x][k^1];
        ch[y][k] = w, fa[w] = y;
        ch[z][ck(y)] = x, fa[x] = z;
        ch[x][k^1] = y, fa[y] = x;
        push_up(y), push_up(x);
    }
    void Splay(int x, int goal = 0) {
        while(fa[x] != goal) {
            int y = fa[x], z = fa[y];
            if(z != goal) {
                if(ck(x) == ck(y)) Rotate(y);
                else Rotate(x);
            }
            Rotate(x);
        }
        if(!goal) rt = x;
    }
    void Find(LL x) {
        if(!rt) return ;
        int cur = rt;
        while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]];
        Splay(cur);
    }
    void Insert(LL x) {
        int cur = rt, p = 0;
        while(cur && val[cur] != x) {
            p = cur;
            cur = ch[cur][x>val[cur]];
        }
        if(cur) cnt[cur]++;
        else {
            cur = ++ncnt;
            if(p) ch[p][x>val[p]] = cur;
            fa[cur] = p;
            ch[cur][0] = ch[cur][1] = 0;
            val[cur] = x;
            cnt[cur] = sz[cur] = 1;
        }
        Splay(cur);
    }
    int Kth(int k) {
        int cur = rt;
        while(true) {
            if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
            else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
            else return cur;
        }
    }
    int Pre(LL x) {
        Find(x);
        if(val[rt] < x) return rt;
        int cur = ch[rt][0];
        while(ch[cur][1]) cur = ch[cur][1];
        return cur;
    }
    int Succ(LL x) {
        Find(x);
        if(val[rt] > x) return rt;
        int cur = ch[rt][1];
        while(ch[cur][0]) cur = ch[cur][0];
        return cur;
    }
    int pre(LL x) {
        Find(x);
        if(val[rt] <= x) return rt;
        int cur = ch[rt][0];
        while(ch[cur][1]) cur = ch[cur][1];
        return cur;
    }
    int succ(LL x) {
        Find(x);
        if(val[rt] >= x) return rt;
        int cur = ch[rt][1];
        while(ch[cur][0]) cur = ch[cur][0];
        return cur;
    }
    void Remove(LL x) {
        int last = Pre(x), next = Succ(x);
        Splay(last), Splay(next, last);
        int del = ch[next][0];
        if(cnt[del] > 1) cnt[del]--, Splay(del);
        else ch[next][0] = 0, push_up(next), push_up(last);
    }
    inline int NewNode(LL x) {
        int cur = ++ncnt;
        ch[cur][0] = ch[cur][1] = fa[cur] = 0;
        val[cur] = x;
        sz[cur] = cnt[cur] = 1;
        return cur;
    }
    inline void init() {
        ncnt = rt = ch[0][0] = ch[0][1] = fa[0] = sz[0] = cnt[0] = val[0] = 0;
    }
}t1, t2;
int T, a, b;
int main() {
    scanf("%d", &T);
    t1.init();
    t2.init();
    t1.Insert(LONG_MIN);
    t1.Insert(LONG_MAX);
    t2.Insert(LONG_MIN);
    t2.Insert(LONG_MAX);
    LL ans = 0;
    while(T--) {
        scanf("%d %d", &a, &b);
        if(a == 0) {
            if(t2.sz[t2.rt] == 2) t1.Insert(b);
            else {
                LL del, tmp = LONG_MAX;
                LL pre = t2.val[t2.pre(b)];
                if(pre != LONG_MIN && abs(pre - b) < tmp) {
                    tmp = abs(pre-b);
                    del = pre;
                }
                LL succ = t2.val[t2.succ(b)];
                if(succ != LONG_MAX && abs(succ - b) < tmp) {
                    tmp = abs(succ-b);
                    del = succ;
                }
                (ans += tmp) %= MOD;
                t2.Remove(del);
            }
        }
        else {
            if(t1.sz[t1.rt] == 2) t2.Insert(b);
            else {
                LL del, tmp = LONG_MAX;
                LL pre = t1.val[t1.pre(b)];
                if(pre != LONG_MIN && abs(pre - b) < tmp) {
                    tmp = abs(pre-b);
                    del = pre;
                }
                LL succ = t1.val[t1.succ(b)];
                if(succ != LONG_MAX && abs(succ - b) < tmp) {
                    tmp = abs(succ-b);
                    del = succ;
                }
                (ans += tmp) %= MOD;
                t1.Remove(del);

            }
        }
    }
    printf("%lld
", ans);
    return 0;
}
View Code

HYSBZ 1269

思路:常规操作,一开始数据范围看错,一直RE

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<climits>
#include<string>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 2.2e6;
int ch[N][2], cnt[N], fa[N], sz[N], lazy[N], ncnt = 0, rt = 0;
char val[N], s[100];
string t;
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
///区间反转
inline void push_down(int x) {
    if(lazy[x]) {
        swap(ch[x][0], ch[x][1]);
        lazy[ch[x][0]] ^= 1;
        lazy[ch[x][1]] ^= 1;
        lazy[x] = 0;
    }
}
void Rotate(int x) {
    int y = fa[x], z = fa[y];
    push_down(y), push_down(x);///区间反转
    int k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    push_down(x);///区间反转
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
void Insert(char x) {
    int cur = rt, p = 0;
    while(cur && val[cur] != x) {
        p = cur;
        cur = ch[cur][x>val[cur]];
    }
    if(cur) cnt[cur]++;
    else {
        cur = ++ncnt;
        if(p) ch[p][x>val[p]] = cur;
        fa[cur] = p;
        ch[cur][0] = ch[cur][1] = 0;
        val[cur] = x;
        cnt[cur] = sz[cur] = 1;
    }
    Splay(cur);
}
int Kth(int k) {
    int cur = rt;
    while(true) {
        push_down(cur); ///区间反转
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return cur;
    }
}
inline int NewNode(char x) {
    int cur = ++ncnt;
    ch[cur][0] = ch[cur][1] = fa[cur] = lazy[cur] = 0;
    val[cur] = x;
    sz[cur] = cnt[cur] = 1;
    return cur;
}
void Reverse(int l, int r) {
    int x = Kth(l), y = Kth(r+2);
    Splay(x), Splay(y, x);
    lazy[ch[y][0]] ^= 1;
}
void Delete(int l, int r) {
    int x = Kth(l), y = Kth(r+2);
    Splay(x), Splay(y, x);
    ch[y][0] = 0;
    push_up(y), push_up(x);
}
int build(int l, int r, string &a) {
    if(l > r) return 0;
    int mid = l+r >> 1, cur = NewNode(a[mid]);
    if(l == r) return cur;
    if(ch[cur][0] = build(l, mid-1, a)) fa[ch[cur][0]] = cur;
    if(ch[cur][1] = build(mid+1, r, a)) fa[ch[cur][1]] = cur;
    push_up(cur);
    return cur;
}
void Insert(int x, int n) {
    int u = Kth(x), v = Kth(x+1);
    Splay(u), Splay(v, u);
    int cur = build(0, n-1, t);
    fa[cur] = v;
    ch[v][0] = cur;
    push_up(v), push_up(u);
    Splay(cur);
}
inline void init() {
    ncnt = rt = ch[0][0] = ch[0][1] = fa[0] = sz[0] = cnt[0] = lazy[0] = 0;
}
int T, n, k, a, b, now = 0;
int main() {
    init();
    Insert('#');
    Insert('*');
    cin >> T;
    for (int i = 0; i < T; ++i) {
        cin >> s;
         if(s[0] == 'M') {
            cin >> k;
            now = k;
        }
        else if(s[0] == 'I') {
            cin >> n;
            cin.ignore();
            getline(cin, t);
            Insert(now+1, n);
        }
        else if(s[0] == 'D') {
            cin >> n;
            Delete(now+1, now+n);
        }
        else if(s[0] == 'R') {
            cin >> n;
            Reverse(now+1, now+n);
        }
        else if(s[0] == 'G') {
            char t = val[Kth(now+2)];
            if(t != '
') putchar(t);
            putchar('
');
        }
        else if(s[0] == 'P') --now;
        else if(s[0] == 'N') ++now;
    }
    return 0;
}
View Code

 POJ 3580

思路:常规操作,REVOLVE记得取模,这个很坑

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<climits>
#include<string>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 2e5 + 10;
int ch[N][2], cnt[N], fa[N], sz[N], lazy[N], ncnt = 0, rt = 0;
LL val[N], a[N], tree[N], add[N];
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    int l = ch[x][0], r = ch[x][1];
    tree[x] = min(val[x], min(tree[l], tree[r]));
    sz[x] = sz[l] + sz[r] + cnt[x];
}
///区间反转
inline void push_down(int x) {
    int l = ch[x][0], r = ch[x][1];
    if(lazy[x]) {
        swap(ch[x][0], ch[x][1]);
        if(l) lazy[l] ^= 1;
        if(r) lazy[r] ^= 1;
        lazy[x] = 0;
    }
    if(add[x]) {
        if(l) val[l] += add[x], tree[l] += add[x], add[l] += add[x];
        if(r) val[r] += add[x], tree[r] += add[x], add[r] += add[x];
        add[x] = 0;
    }
}
void Rotate(int x) {
    int y = fa[x], z = fa[y];
    push_down(y), push_down(x);///区间反转
    int k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    push_down(x);///区间反转
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}

int Kth(int k) {
    int cur = rt;
    while(true) {
        push_down(cur); ///区间反转
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return cur;
    }
}
inline int NewNode(LL x) {
    int cur = ++ncnt;
    ch[cur][0] = ch[cur][1] = fa[cur] = add[cur] = lazy[cur] = 0;
    val[cur] = x;
    tree[cur] = x;
    sz[cur] = cnt[cur] = 1;
    return cur;
}
///区间反转
void REVERSE(int l, int r) {
    int x = Kth(l), y = Kth(r+2);
    Splay(x), Splay(y, x);
    int cur = ch[y][0];
    lazy[cur] ^= 1;
}
void ADD(int l, int r, LL z) {
    int x = Kth(l), y = Kth(r+2);
    Splay(x), Splay(y, x);
    val[ch[y][0]] += z;
    tree[ch[y][0]] += z;
    add[ch[y][0]] += z;
    push_up(y), push_up(x);
}
void REVOLVE(int l, int r, int z) {
    int len = r-l+1;
    z = (z%len + len) % len;
    if(!z) return ;
    int ll = r-z+1, rr = r;
    int x = Kth(ll), y = Kth(rr+2);
    Splay(x), Splay(y, x);
    int cur = ch[y][0];
    ch[y][0] = 0;
    push_up(y), push_up(x);
    x = Kth(l), y = Kth(l+1);
    Splay(x), Splay(y, x);
    ch[y][0] = cur;
    fa[cur] = y;
    push_up(y), push_up(x);
    Splay(cur);
}
LL MIN(int l, int r) {
    int x = Kth(l), y = Kth(r+2);
    Splay(x), Splay(y, x);
    return tree[ch[y][0]];
}
void INSERT(int x, LL y) {
    int u = Kth(x+1), v = Kth(x+2);
    Splay(u), Splay(v, u);
    int cur = NewNode(y);
    fa[cur] = v;
    ch[v][0] = cur;
    push_up(v), push_up(u);
}
void DELETE(int x) {
    int u = Kth(x), v = Kth(x+2);
    Splay(u), Splay(v, u);
    ch[v][0] = 0;
    push_up(v), push_up(u);
}
int build(int l, int r, LL *a) {
    if(l > r) return 0;
    int mid = l+r >> 1, cur = NewNode(a[mid]);
    if(l == r) return cur;
    if(ch[cur][0] = build(l, mid-1, a)) fa[ch[cur][0]] = cur;
    if(ch[cur][1] = build(mid+1, r, a)) fa[ch[cur][1]] = cur;
    push_up(cur);
    return cur;
}
inline void init() {
    ncnt = rt = ch[0][0] = ch[0][1] = fa[0] = sz[0] = cnt[0] = val[0] = add[0] = lazy[0] = 0;
    tree[0] = LONG_MAX;
}
int n, m, x, y;
LL z;
char s[100];
int main() {
    init();
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
    a[0] = a[n+1] = LONG_MAX;
    rt = build(0, n+1, a);
    scanf("%d", &m);
    for (int i = 1; i <= m; ++i) {
        scanf("%s", s);
        if(s[0] == 'A') {
            scanf("%d %d %lld", &x, &y, &z);
            ADD(x, y, z);
        }
        else if(s[0] == 'R' && s[3] == 'E') {
            scanf("%d %d", &x, &y);
            REVERSE(x, y);
        }
        else if(s[0] == 'R' && s[3] == 'O') {
            scanf("%d %d %lld", &x, &y, &z);
            REVOLVE(x, y, z);
        }
        else if(s[0] == 'I') {
            scanf("%d %d", &x, &y);
            INSERT(x, y);
        }
        else if(s[0] == 'D') {
            scanf("%d", &x);
            DELETE(x);
        }
        else if(s[0] == 'M') {
            scanf("%d %d", &x, &y);
            printf("%lld
", MIN(x, y));
        }
    }
    return 0;
}
View Code

POJ 3468

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<climits>
#include<cstring>
using namespace std;
#define LL long long

const int N = 1e5 + 10;
int ch[N][2], cnt[N], fa[N], sz[N], ncnt = 0, rt = 0;
LL add[N], tree[N], val[N], a[N];
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
    tree[x] = val[x] + tree[ch[x][0]] + tree[ch[x][1]];
}
///区间反转
inline void push_down(int x) {
    if(add[x]) {
        int l = ch[x][0], r = ch[x][1];
        if(l) add[l] += add[x], val[l] += add[x], tree[l] += sz[l]*1LL*add[x];
        if(r) add[r] += add[x], val[r] += add[x], tree[r] += sz[r]*1LL*add[x];
        add[x] = 0;
    }
}
void Rotate(int x) {
    int y = fa[x], z = fa[y];
    push_down(y), push_down(x);///区间反转
    int k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    push_down(x);///区间反转
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
int Kth(int k) {
    int cur = rt;
    while(true) {
        push_down(cur); ///区间反转
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return cur;
    }
}
void ADD(int l, int r, LL c) {
    int x = Kth(l), y = Kth(r+2);
    Splay(x), Splay(y, x);
    add[ch[y][0]] += c;
    tree[ch[y][0]] += sz[ch[y][0]]*1LL*c;
    val[ch[y][0]] += c;
    push_up(y), push_up(x);
}
LL SUM(int l, int r) {
    int x = Kth(l), y = Kth(r+2);
    Splay(x), Splay(y, x);
    return tree[ch[y][0]];
}
inline int NewNode(LL x) {
    int cur;cur = ++ncnt;
    ch[cur][0] = ch[cur][1] = fa[cur] = add[cur] = 0;
    val[cur] = x;
    tree[cur] = x;
    sz[cur] = cnt[cur] = 1;
    return cur;
}

int build(int l, int r, LL *a) {
    if(l > r) return 0;
    int mid = l+r >> 1, cur = NewNode(a[mid]);
    if(l == r) return cur;
    if(ch[cur][0] = build(l, mid-1, a)) fa[ch[cur][0]] = cur;
    if(ch[cur][1] = build(mid+1, r, a)) fa[ch[cur][1]] = cur;
    push_up(cur);
    return cur;
}
inline void init() {
    ncnt = rt = ch[0][0] = ch[0][1] = fa[0] = sz[0] = cnt[0] = val[0] = add[0] = tree[0] = 0;
}
int n, m, l, r;
LL c;
char s[100];
int main() {
    init();
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
    rt = build(0, n+1, a);
    for (int i = 1; i <= m; ++i) {
        scanf("%s", s);
        if(s[0] == 'Q') {
            scanf("%d %d", &l, &r);
            printf("%lld
", SUM(l, r));
        }
        else if(s[0] == 'C') {
            scanf("%d %d %lld", &l, &r, &c);
            ADD(l, r, c);
        }
    }
    return 0;
}
View Code

 HDU 2475

将树按入时间戳和出时间戳变成线性结构,然后在这个线性结构上用splay维护

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 100;
int ch[N][2], val[N], cnt[N], fa[N], sz[N], ncnt = 0, rt = 0;
int n, m, a, now = 0;
vector<int> g[N];
int L[N], R[N], dfn[N], x, y;
char s[100];
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
void Rotate(int x) {
    int y = fa[x], z = fa[y];
    int k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
}
void Splay(int x, int goal = 0) {
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
inline int NewNode(int x) {
    int cur = ++ncnt;
    ch[cur][0] = ch[cur][1] = fa[cur]  = 0;
    val[cur] = abs(x);
    if(x > 0) L[x] = cur;
    else R[-x] = cur;
    return cur;
}
int build(int l, int r, int *a) {
    if(l > r) return 0;
    int mid = l+r >> 1, cur = NewNode(a[mid]);
    if(l == r) return cur;
    if(ch[cur][0] = build(l, mid-1, a)) fa[ch[cur][0]] = cur;
    if(ch[cur][1] = build(mid+1, r, a)) fa[ch[cur][1]] = cur;
    return cur;
}
inline void init() {
    ncnt = rt = ch[0][0] = ch[0][1] = fa[0] = val[0] = 0;
}
void dfs(int u) {
    dfn[++now] = u;
    for (int v : g[u]) dfs(v);
    dfn[++now] = -u;
}
inline int get_min(int x) {
    while(x && ch[x][0]) x = ch[x][0];
    return x;
}
inline int get_max(int x) {
    while(x && ch[x][1]) x = ch[x][1];
    return x;
}
int QUERY(int x) {
    int u = L[x];
    Splay(u);
    return get_min(u);
}
void MOVE(int X, int Y) {
    int u = L[X], v = R[X];
    Splay(u), Splay(v, u);
    int x = ch[u][0], y = ch[v][1];
    int xx = get_max(x);
    fa[x] = 0, ch[u][0] = 0;
    fa[y] = 0, ch[v][1] = 0;
    if(y && xx) ch[xx][1] = y, fa[y] = xx;

    if(Y == 0) return ;
    if(QUERY(Y) == u) {
        fa[x] = u, ch[u][0] = x;
        fa[y] = v, ch[v][1] = y;
        ch[xx][1] = 0;
        return ;
    }

    int uu = L[Y];
    Splay(uu);
    int vv = get_min(ch[uu][1]);
    Splay(vv, uu);
    ch[vv][0] = u;
    fa[u] = vv;
}
int main() {
    bool f = false;
    while(~scanf("%d", &n)) {
        if(f) printf("
");
        else f = true;
        init();
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a);
            g[a].pb(i);
        }
        for (int u : g[0]) {
            now = 0;
            dfs(u);
            build(1, now, dfn);
        }
        scanf("%d", &m);
        for (int i = 1; i <= m; ++i) {
            scanf("%s", s);
            if(s[0] == 'M') {
                scanf("%d %d", &x, &y);
                MOVE(x, y);
            }
            else if(s[0] == 'Q') {
                scanf("%d", &x);
                printf("%d
", val[QUERY(x)]);
            }
        }
        for (int i = 0; i <= n; ++i) g[i].clear();
    }
    return 0;
}
View Code

易错点:

1.修改后记得push_up

2.一直往左子树或右子树走时记得第一步判当前节点是不是0

套板子一时爽,一直套一直爽

Link-Cut-Tree

模板:

const int N = 3e5 + 5;
int f[N],v[N],s[N],r[N],hep[N],ch[N][2];
inline int get(int x){
    return ch[f[x]][0]==x||ch[f[x]][1]==x;
}
inline void pushup(int x){
    s[x]=s[ch[x][1]]^s[ch[x][0]]^v[x];
}
inline void filp(int x){
    swap(ch[x][0],ch[x][1]);r[x]^=1;
}
inline void pushdown(int x){
    if(!r[x])return;r[x]=0;
    if(ch[x][0])filp(ch[x][0]);
    if(ch[x][1])filp(ch[x][1]);
}
inline void rotate(int x){
    int y=f[x],z=f[y],k=ch[y][1]==x,v=ch[x][!k];
    if(get(y))ch[z][ch[z][1]==y]=x;ch[x][!k]=y,ch[y][k]=v;
    if(v)f[v]=y;f[y]=x,f[x]=z;pushup(y),pushup(x);
}
inline void Splay(int x){
    int y=x,top=0;hep[++top]=y;
    while(get(y))hep[++top]=y=f[y];
    while(top)pushdown(hep[top--]);
    while(get(x)){
        y=f[x],top=f[y];
        if(get(y))
           rotate((ch[y][0]==x)^(ch[top][0]==y)?x:y);
        rotate(x);
    }pushup(x);return;
}
inline void Access(int x){
    for(register int y=0;x;x=f[y=x])
       Splay(x),ch[x][1]=y,pushup(x);
}
inline void makeroot(int x){
    Access(x);Splay(x);filp(x);
}
inline int findroot(int x){
    Access(x);Splay(x);
    while(ch[x][0])pushdown(x),x=ch[x][0];
    return x;
}
inline void split(int x,int y){
    makeroot(x);Access(y);Splay(y);
}
inline void link(int x,int y){
    makeroot(x);if(findroot(y)!=x)f[x]=y;
}
inline void cut(int x,int y){
    split(x,y);
    if(findroot(y)==x&&f[x]==y&&!ch[x][1]){
        f[x]=ch[y][0]=0;pushup(y);
    }return;
}

 P3690 【模板】Link Cut Tree (动态树) 

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 3e5 + 5;
int f[N],v[N],s[N],r[N],hep[N],ch[N][2];
inline int get(int x){
    return ch[f[x]][0]==x||ch[f[x]][1]==x;
}
inline void pushup(int x){
    s[x]=s[ch[x][1]]^s[ch[x][0]]^v[x];
}
inline void filp(int x){
    swap(ch[x][0],ch[x][1]);r[x]^=1;
}
inline void pushdown(int x){
    if(!r[x])return;r[x]=0;
    if(ch[x][0])filp(ch[x][0]);
    if(ch[x][1])filp(ch[x][1]);
}
inline void rotate(int x){
    int y=f[x],z=f[y],k=ch[y][1]==x,v=ch[x][!k];
    if(get(y))ch[z][ch[z][1]==y]=x;ch[x][!k]=y,ch[y][k]=v;
    if(v)f[v]=y;f[y]=x,f[x]=z;pushup(y),pushup(x);
}
inline void Splay(int x){
    int y=x,top=0;hep[++top]=y;
    while(get(y))hep[++top]=y=f[y];
    while(top)pushdown(hep[top--]);
    while(get(x)){
        y=f[x],top=f[y];
        if(get(y))
           rotate((ch[y][0]==x)^(ch[top][0]==y)?x:y);
        rotate(x);
    }pushup(x);return;
}
inline void Access(int x){
    for(register int y=0;x;x=f[y=x])
       Splay(x),ch[x][1]=y,pushup(x);
}
inline void makeroot(int x){
    Access(x);Splay(x);filp(x);
}
inline int findroot(int x){
    Access(x);Splay(x);
    while(ch[x][0])pushdown(x),x=ch[x][0];
    return x;
}
inline void split(int x,int y){
    makeroot(x);Access(y);Splay(y);
}
inline void link(int x,int y){
    makeroot(x);if(findroot(y)!=x)f[x]=y;
}
inline void cut(int x,int y){
    split(x,y);
    if(findroot(y)==x&&f[x]==y&&!ch[x][1]){
        f[x]=ch[y][0]=0;pushup(y);
    }return;
}
int n, m, op, x, y;
int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i) scanf("%d", &v[i]);
    for (int i = 1; i <= m; ++i) {
        scanf("%d %d %d", &op, &x, &y);
        if(op == 0) split(x, y), printf("%d
", s[y]);
        else if(op == 1) link(x, y);
        else if(op == 2) cut(x, y);
        else Splay(x), v[x] = y;
    }
    return 0;
}
View Code

HYSBZ 1036

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e4 + 10;
int f[N], r[N],hep[N],ch[N][2];
inline int get(int x){
    return ch[f[x]][0]==x||ch[f[x]][1]==x;
}
inline void pushup(int x){
   return ;
}
inline void filp(int x){
    swap(ch[x][0],ch[x][1]);r[x]^=1;
}
inline void pushdown(int x){
    if(!r[x])return;r[x]=0;
    if(ch[x][0])filp(ch[x][0]);
    if(ch[x][1])filp(ch[x][1]);
}
inline void rotate(int x){
    int y=f[x],z=f[y],k=ch[y][1]==x,v=ch[x][!k];
    if(get(y))ch[z][ch[z][1]==y]=x;ch[x][!k]=y,ch[y][k]=v;
    if(v)f[v]=y;f[y]=x,f[x]=z;pushup(y),pushup(x);
}
inline void Splay(int x){
    int y=x,top=0;hep[++top]=y;
    while(get(y))hep[++top]=y=f[y];
    while(top)pushdown(hep[top--]);
    while(get(x)){
        y=f[x],top=f[y];
        if(get(y))
           rotate((ch[y][0]==x)^(ch[top][0]==y)?x:y);
        rotate(x);
    }pushup(x);return;
}
inline void Access(int x){
    for(register int y=0;x;x=f[y=x])
       Splay(x),ch[x][1]=y,pushup(x);
}
inline void makeroot(int x){
    Access(x);Splay(x);filp(x);
}
inline int findroot(int x){
    Access(x);Splay(x);
    while(ch[x][0])pushdown(x),x=ch[x][0];
    return x;
}
inline void split(int x,int y){
    makeroot(x);Access(y);Splay(y);
}
inline void link(int x,int y){
    makeroot(x);if(findroot(y)!=x)f[x]=y;
}
inline void cut(int x,int y){
    split(x,y);
    if(findroot(y)==x&&f[x]==y&&!ch[x][1]){
        f[x]=ch[y][0]=0;pushup(y);
    }return;
}
char op[100];
int n, m, u, v;
int main() {
    scanf("%d", &n);
    scanf("%d", &m);
    for (int i = 1; i <= m; ++i) {
        scanf("%s %d %d", op, &u, &v);
        if(op[0] == 'C') link(u, v);
        else if(op[0] == 'D') cut(u, v);
        else {
            makeroot(u);
            if(findroot(v) != u) printf("No
");
            else printf("Yes
");
        }
    }
    return 0;
}
View Code

HDU 4010

思路:注意cut和普通的cut不一样

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 3e5 + 5;
int f[N],v[N],mx[N],r[N],add[N], hep[N],ch[N][2];
inline int get(int x){
    return ch[f[x]][0]==x||ch[f[x]][1]==x;
}
inline void pushup(int x){
    mx[x]= max(max(mx[ch[x][1]], mx[ch[x][0]]), v[x]);
}
inline void filp(int x){
    swap(ch[x][0],ch[x][1]);r[x]^=1;
}
inline void pushdown(int x){
    int ls = ch[x][0], rs = ch[x][1];
    if(r[x]) {
        if(ls) filp(ls);
        if(rs) filp(rs);
        r[x] = 0;
    }
    if(add[x]) {
        if(ls) add[ls] += add[x], v[ls] += add[x], mx[ls] += add[x];
        if(rs) add[rs] += add[x], v[rs] += add[x], mx[rs] += add[x];
        add[x] = 0;
    }
}
inline void rotate(int x){
    int y=f[x],z=f[y],k=ch[y][1]==x,v=ch[x][!k];
    if(get(y))ch[z][ch[z][1]==y]=x;ch[x][!k]=y,ch[y][k]=v;
    if(v)f[v]=y;f[y]=x,f[x]=z;pushup(y),pushup(x);
}
inline void Splay(int x){
    int y=x,top=0;hep[++top]=y;
    while(get(y))hep[++top]=y=f[y];
    while(top)pushdown(hep[top--]);
    while(get(x)){
        y=f[x],top=f[y];
        if(get(y))
           rotate((ch[y][0]==x)^(ch[top][0]==y)?x:y);
        rotate(x);
    }pushup(x);return;
}
inline void Access(int x){
    for(register int y=0;x;x=f[y=x])
       Splay(x),ch[x][1]=y,pushup(x);
}
inline void makeroot(int x){
    Access(x);Splay(x);filp(x);
}
inline int findroot(int x){
    Access(x);Splay(x);
    while(ch[x][0])pushdown(x),x=ch[x][0];
    return x;
}
inline void ADD(int x,int y, int w){
    makeroot(x);Access(y);Splay(y);
    v[y] += w, add[y] += w, mx[y] += w;
}
inline void split(int x,int y){
    makeroot(x);Access(y);Splay(y);
}
inline void link(int x,int y){
    makeroot(x); if(findroot(y)!=x)f[x]=y;
}
inline void cut(int x,int y) {
    split(x,y);
    ch[y][0] = f[ch[y][0]] = 0;
}
int op, x, y, w, n, m;
int U[N], V[N];
int main() {
    while(~scanf("%d", &n)) {
        mx[0] = INT_MIN;
        for (int i = 1; i < n; ++i) scanf("%d %d", &U[i], &V[i]);
        for (int i = 1; i <= n; ++i) scanf("%d", &v[i]), mx[i] = v[i], add[i] = r[i] = ch[i][0] = ch[i][1] = f[i] = 0;
        for (int i = 1; i < n; ++i) link(U[i], V[i]);
        scanf("%d", &m);
        for (int i = 1; i <= m; ++i) {
            scanf("%d", &op);
            if(op == 1) {
                scanf("%d %d", &x, &y);
                if(findroot(x) == findroot(y)) printf("-1
");
                else link(x, y);
            }
            else if(op == 2){
                scanf("%d %d", &x, &y);
                if(findroot(x) != findroot(y) || x == y) printf("-1
");
                else cut(x, y);
            }
            else if(op == 3) {
                scanf("%d %d %d", &w, &x, &y);
                if(findroot(x) != findroot(y)) printf("-1
");
                else ADD(x, y, w);
            }
            else {
                scanf("%d %d", &x, &y);
                if(findroot(x) != findroot(y)) printf("-1
");
                else split(x, y), printf("%d
", mx[y]);
            }
        }
        printf("
");
    }
    return 0;
}
View Code

URAL 1553

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
int f[N],v[N],mx[N],r[N],hep[N],ch[N][2];
inline int get(int x){
    return ch[f[x]][0]==x||ch[f[x]][1]==x;
}
inline void pushup(int x){
    mx[x] = max(max(mx[ch[x][0]], mx[ch[x][1]]), v[x]);
}
inline void filp(int x){
    swap(ch[x][0],ch[x][1]);r[x]^=1;
}
inline void pushdown(int x){
    if(!r[x])return;r[x]=0;
    if(ch[x][0])filp(ch[x][0]);
    if(ch[x][1])filp(ch[x][1]);
}
inline void Rotate(int x){
    int y=f[x],z=f[y],k=ch[y][1]==x,v=ch[x][!k];
    if(get(y))ch[z][ch[z][1]==y]=x;ch[x][!k]=y,ch[y][k]=v;
    if(v)f[v]=y;f[y]=x,f[x]=z;pushup(y),pushup(x);
}
inline void Splay(int x){
    int y=x,top=0;hep[++top]=y;
    while(get(y))hep[++top]=y=f[y];
    while(top)pushdown(hep[top--]);
    while(get(x)){
        y=f[x],top=f[y];
        if(get(y))
           Rotate((ch[y][0]==x)^(ch[top][0]==y)?x:y);
        Rotate(x);
    }pushup(x);return;
}
inline void Access(int x){
    for(int y=0;x;x=f[y=x])
       Splay(x),ch[x][1]=y,pushup(x);
}
inline void makeroot(int x){
    Access(x);Splay(x);filp(x);
}
inline int findroot(int x){
    Access(x);Splay(x);
    while(ch[x][0])pushdown(x),x=ch[x][0];
    return x;
}
inline void split(int x,int y){
    makeroot(x);Access(y);Splay(y);
}
inline void link(int x,int y){
    makeroot(x);if(findroot(y)!=x)f[x]=y;
}
inline void cut(int x,int y){
    split(x,y);
    if(findroot(y)==x&&f[x]==y&&!ch[x][1]){
        f[x]=ch[y][0]=0;pushup(y);
    }return;
}
int n, m, x, y;
char op[100];
int main() {
    mx[0] = INT_MIN;
    scanf("%d", &n);
    for (int i = 1; i < n; ++i) scanf("%d%d", &x, &y), link(x, y);
    scanf("%d", &m);
    for (int i = 1; i <= m; ++i) {
        scanf("%s%d%d", op, &x, &y);
        if(op[0] == 'I') Splay(x), v[x] += y;
        else split(x, y), printf("%d
", mx[y]);
    }
    return 0;
}
View Code

SPOJ OTOCI

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 3e4 + 5;
int f[N],s[N], v[N],r[N],hep[N],ch[N][2];
inline int get(int x){
    return ch[f[x]][0]==x||ch[f[x]][1]==x;
}
inline void pushup(int x){
    s[x] = s[ch[x][0]] + s[ch[x][1]] + v[x];
}
inline void filp(int x){
    swap(ch[x][0],ch[x][1]);r[x]^=1;
}
inline void pushdown(int x){
    if(!r[x])return;r[x]=0;
    if(ch[x][0])filp(ch[x][0]);
    if(ch[x][1])filp(ch[x][1]);
}
inline void rotate(int x){
    int y=f[x],z=f[y],k=ch[y][1]==x,v=ch[x][!k];
    if(get(y))ch[z][ch[z][1]==y]=x;ch[x][!k]=y,ch[y][k]=v;
    if(v)f[v]=y;f[y]=x,f[x]=z;pushup(y),pushup(x);
}
inline void Splay(int x){
    int y=x,top=0;hep[++top]=y;
    while(get(y))hep[++top]=y=f[y];
    while(top)pushdown(hep[top--]);
    while(get(x)){
        y=f[x],top=f[y];
        if(get(y))
           rotate((ch[y][0]==x)^(ch[top][0]==y)?x:y);
        rotate(x);
    }pushup(x);return;
}
inline void Access(int x){
    for(register int y=0;x;x=f[y=x])
       Splay(x),ch[x][1]=y,pushup(x);
}
inline void makeroot(int x){
    Access(x);Splay(x);filp(x);
}
inline int findroot(int x){
    Access(x);Splay(x);
    while(ch[x][0])pushdown(x),x=ch[x][0];
    return x;
}
inline void split(int x,int y){
    makeroot(x);Access(y);Splay(y);
}
inline bool link(int x,int y){
    makeroot(x);if(findroot(y)!=x)f[x]=y; else return false;
    return true;
}
inline void cut(int x,int y){
    split(x,y);
    if(findroot(y)==x&&f[x]==y&&!ch[x][1]){
        f[x]=ch[y][0]=0;pushup(y);
    }return;
}
int n, m, x, y;
char op[100];
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%d", &v[i]);
    scanf("%d", &m);
    for (int i = 1; i <= m; ++i) {
        scanf("%s %d %d", op, &x, &y);
        if(op[0] == 'b') {
            if(link(x, y)) printf("yes
");
            else printf("no
");
        }
        else if(op[0] == 'p') {
            Splay(x);
            v[x] = y;
        }
        else {
            if(findroot(x) != findroot(y)) printf("impossible
");
            else split(x, y), printf("%d
", s[y]);

        }
    }
    return 0;
}
View Code

FHQ Treap

参考:https://blog.csdn.net/pengwill97/article/details/82891241

模板:

struct fhq_treap {
    static const int N = 1e5 + 5;
    struct Node {
        int val, key, lc, rc, sz;
    }tree[N];
    int rt, tot;
    inline void init() {
        rt = tot = 0;
        tree[rt].sz = tree[rt].val = tree[rt].lc = tree[rt].rc = 0;
        srand(time(0));
    }
    inline void update(int rt) {
        tree[rt].sz = tree[tree[rt].lc].sz + tree[tree[rt].rc].sz + 1;
    }
    void split(int rt, int &a, int &b, int val) {
        if(rt == 0) {a = b = 0; return ;}
        if(tree[rt].val <= val) {
            a = rt;
            split(tree[rt].rc, tree[a].rc, b, val);
        }
        else {
            b = rt;
            split(tree[rt].lc, a, tree[b].lc, val);
        }
        update(rt);
    }
    void merge(int &rt, int a, int b) {
        if(a==0 || b==0) {
            rt = a+b;
            return ;
        }
        if(tree[a].key < tree[b].key) {
            rt = a;
            merge(tree[rt].rc, tree[a].rc, b);
        }
        else {
            rt = b;
            merge(tree[rt].lc, a, tree[b].lc);
        }
        update(rt);
    }
    inline int new_node(int val) {
        tree[++tot].sz = 1;
        tree[tot].val = val;
        tree[tot].lc = tree[tot].rc = 0;
        tree[tot].key = rand()*rand();
        return tot;
    }
    void ins(int &rt, int val) {
        int x = 0, y = 0, node = new_node(val);
        split(rt, x, y, val);
        merge(x, x, node);
        merge(rt, x, y);
    }
    void delete_node(int &rt, int val) {
        int x = 0, y = 0, z = 0;
        split(rt, x, y, val);
        split(x, x, z, val-1);
        merge(z, tree[z].lc, tree[z].rc);
        merge(x, x, z);
        merge(rt, x, y);
    }
    inline int get_kth(int rt, int k) {
        while(tree[tree[rt].lc].sz+1 != k) {
            if(tree[tree[rt].lc].sz >= k) rt = tree[rt].lc;
            else k -= tree[tree[rt].lc].sz+1, rt = tree[rt].rc;
        }
        return tree[rt].val;
    }
    int get_rnk(int &rt, int val) {
        int x = 0, y = 0;
        split(rt, x, y, val-1);
        int tmp = tree[x].sz+1;
        merge(rt, x, y);
        return tmp;
    }
    int get_pre(int &rt, int val) {
        int x = 0, y = 0;
        split(rt, x,  y, val-1);
        int tmp = get_kth(x, tree[x].sz);
        merge(rt, x, y);
        return tmp;
    }
    int get_scc(int &rt, int val) {
        int x = 0, y = 0;
        split(rt, x, y, val);
        int tmp = get_kth(y, 1);
        merge(rt, x, y);
        return tmp;
    }
}t;

例题:

P3369 【模板】普通平衡树 

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head


struct fhq_treap {
    static const int N = 1e5 + 5;
    struct Node {
        int val, key, lc, rc, sz;
    }tree[N];
    int rt, tot;
    inline void init() {
        rt = tot = 0;
        tree[rt].sz = tree[rt].val = tree[rt].lc = tree[rt].rc = 0;
        srand(time(0));
    }
    inline void update(int rt) {
        tree[rt].sz = tree[tree[rt].lc].sz + tree[tree[rt].rc].sz + 1;
    }
    void split(int rt, int &a, int &b, int val) {
        if(rt == 0) {a = b = 0; return ;}
        if(tree[rt].val <= val) {
            a = rt;
            split(tree[rt].rc, tree[a].rc, b, val);
        }
        else {
            b = rt;
            split(tree[rt].lc, a, tree[b].lc, val);
        }
        update(rt);
    }
    void merge(int &rt, int a, int b) {
        if(a==0 || b==0) {
            rt = a+b;
            return ;
        }
        if(tree[a].key < tree[b].key) {
            rt = a;
            merge(tree[rt].rc, tree[a].rc, b);
        }
        else {
            rt = b;
            merge(tree[rt].lc, a, tree[b].lc);
        }
        update(rt);
    }
    inline int new_node(int val) {
        tree[++tot].sz = 1;
        tree[tot].val = val;
        tree[tot].lc = tree[tot].rc = 0;
        tree[tot].key = rand()*rand();
        return tot;
    }
    void ins(int &rt, int val) {
        int x = 0, y = 0, node = new_node(val);
        split(rt, x, y, val);
        merge(x, x, node);
        merge(rt, x, y);
    }
    void delete_node(int &rt, int val) {
        int x = 0, y = 0, z = 0;
        split(rt, x, y, val);
        split(x, x, z, val-1);
        merge(z, tree[z].lc, tree[z].rc);///???
        merge(x, x, z);
        merge(rt, x, y);
    }
    inline int get_kth(int rt, int k) {
        while(tree[tree[rt].lc].sz+1 != k) {
            if(tree[tree[rt].lc].sz >= k) rt = tree[rt].lc;
            else k -= tree[tree[rt].lc].sz+1, rt = tree[rt].rc;
        }
        return tree[rt].val;
    }
    int get_rnk(int &rt, int val) {
        int x = 0, y = 0;
        split(rt, x, y, val-1);
        int tmp = tree[x].sz+1;
        merge(rt, x, y);
        return tmp;
    }
    int get_pre(int &rt, int val) {
        int x = 0, y = 0;
        split(rt, x,  y, val-1);
        int tmp = get_kth(x, tree[x].sz);
        merge(rt, x, y);
        return tmp;
    }
    int get_scc(int &rt, int val) {
        int x = 0, y = 0;
        split(rt, x, y, val);
        int tmp = get_kth(y, 1);
        merge(rt, x, y);
        return tmp;
    }
}t;
int n, op, x;
int main() {
    t.init();
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d %d", &op, &x);
        if(op == 1) t.ins(t.rt, x);
        else if(op == 2) t.delete_node(t.rt, x);
        else if(op == 3) printf("%d
", t.get_rnk(t.rt, x));
        else if(op == 4) printf("%d
", t.get_kth(t.rt, x));
        else if(op == 5) printf("%d
", t.get_pre(t.rt, x));
        else printf("%d
", t.get_scc(t.rt, x));
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/widsom/p/10604057.html