BZOJ 1861 书架

平衡树

随便一个splay搞搞就行啦~~

需要一个pos数组来查找书编号为i的节点号

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
using namespace std;
typedef long long ll;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
    int X = 0, w = 0; char ch = 0;
    while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
    while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    return w ? -X : X;
}
inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
template<typename T>
inline T max(T x, T y, T z){ return max(max(x, y), z); }
template<typename T>
inline T min(T x, T y, T z){ return min(min(x, y), z); }
template<typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
    A ans = 1;
    for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
    return ans;
}
const int N = 80005;
int n, m, tot, root, ch[N][2], fa[N], pos[N], size[N], val[N], a[N];

int init(int v, int f){
    ++tot;
    val[tot] = v, size[tot] = 1, pos[v] = tot, fa[tot] = f;
    ch[tot][0] = ch[tot][1] = 0;
    return tot;
}

void push_up(int x){
    int l = ch[x][0], r = ch[x][1];
    size[x] = size[l] + size[r] + 1;
    pos[val[x]] = x;
}

void rotate(int x){
    int y = fa[x], z = fa[y], p = (ch[y][1] == x) ^ 1;
    ch[y][p^1] = ch[x][p], fa[ch[x][p]] = y;
    ch[z][ch[z][1] == y] = x, fa[x] = z;
    ch[x][p] = y, fa[y] = x;
    push_up(y), push_up(x);
}

void splay(int x, int goal){
    if(x == goal) return;
    while(fa[x] != goal){
        int y = fa[x], z = fa[y];
        if(z != goal){
            (ch[y][0] == x) ^ (ch[z][0] == y) ? rotate(x) : rotate(y);
        }
        rotate(x);
    }
    push_up(x);
    if(goal == 0) root = x;
}

void top(int x){
    splay(pos[x], 0);
    if(!ch[root][0]) return;
    if(!ch[root][1]){
        ch[root][1] = ch[root][0], ch[root][0] = 0;
        return;
    }
    int cur = ch[root][1];
    while(ch[cur][0]) cur = ch[cur][0];
    ch[cur][0] = ch[root][0], fa[ch[root][0]] = cur;
    ch[root][0] = 0;
    splay(ch[cur][0], 0);
}

void bottom(int x){
    splay(pos[x], 0);
    if(!ch[root][1]) return;
    if(!ch[root][0]){
        ch[root][0] = ch[root][1], ch[root][1] = 0;
        return;
    }
    else{
        int cur = ch[root][0];
        while(ch[cur][1]) cur = ch[cur][1];
        ch[cur][1] = ch[root][1], fa[ch[root][1]] = cur;
        ch[root][1] = 0;
        splay(ch[cur][1], 0);
    }
}

void insert(int x, int t){
    splay(pos[x], 0);
    if(!t) return;
    int p = t == 1 ? 1 : 0;
    int cur = ch[root][p];
    while(ch[cur][p^1]) cur = ch[cur][p^1];
    int tmp = pos[x], to = val[cur];
    swap(val[tmp], val[cur]);
    swap(pos[x], pos[to]);
    splay(ch[root][p], 0);
}

int ask(int x){
    splay(pos[x], 0);
    return size[ch[root][0]];
}

int query(int x){
    int cur = root, p = size[ch[root][0]];
    while(1){
        if(x > p + 1){
            cur = ch[cur][1];
            x -= p + 1;
        }
        else{
            if(p >= x) cur = ch[cur][0];
            else return val[cur];
        }
        p = size[ch[cur][0]];
    }
}

int buildTree(int x, int l, int r){
    if(l > r) return 0;
    int mid = (l + r) >> 1;
    int p = init(a[mid], x);
    ch[p][0] = buildTree(p, l, mid - 1);
    ch[p][1] = buildTree(p, mid + 1, r);
    push_up(p);
    return p;
}

int main(){

    n = read(), m = read();
    for(int i = 1; i <= n; i ++) a[i] = read();
    root = buildTree(0, 1, n);
    while(m --){
        char opt[20]; scanf("%s", opt);
        int s = read();
        if(opt[0] == 'T') top(s);
        else if(opt[0] == 'B') bottom(s);
        else if(opt[0] == 'I') { int x = read(); insert(s, x); }
        else if(opt[0] == 'A') printf("%d\n", ask(s));
        else if(opt[0] == 'Q') printf("%d\n", query(s));
    }
    return 0;
}
posted @ 2019-04-24 20:02  清楚少女ひなこ  阅读(150)  评论(0编辑  收藏  举报