bzoj3224 Tyvj 1728 普通平衡树

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3224

【题解】

写起来跟*一样,但是还是挺快调出来了。

主要就是每个数可以有多个,我们可以用一个splay节点存多个数,然后find即可。

注意的是每个操作过后基本都要splay一下保证复杂度。

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 1e5 + 10;
const int mod = 1e9+7;
const int inf = 2e9 + 10;

# define RG register
# define ST static

struct Splay {
    int ch[M][2], fa[M]; int val[M], sz[M], rt, siz, s[M];
    inline void set() {
        siz = 2; rt = 1;
        ch[1][0] = ch[2][0] = ch[2][1] = fa[1] = 0, ch[1][1] = 2; fa[2] = 1;
        sz[1] = 2, sz[2] = 1; val[1] = -inf, val[2] = inf; s[1] = s[2] = 1;
    }
    inline void up(int x) {
        if(!x) return ;
        sz[x] = s[x] + sz[ch[x][0]] + sz[ch[x][1]];
    }
    inline void rotate(int x, int &rt) {
        int y = fa[x], z = fa[y], ls = ch[y][1] == x, rs = ls^1;
        if(rt == y) rt = x;
        else ch[z][ch[z][1] == y] = x;
        fa[ch[x][rs]] = y, fa[y] = x, fa[x] = z;
        ch[y][ls] = ch[x][rs]; ch[x][rs] = y;
        up(y); up(x);
    }
    inline void splay(int x, int &rt) {
        while(x != rt) {
            int y = fa[x], z = fa[y];
            if(y != rt) {
                if((ch[z][0] == y) ^ (ch[y][0] == x)) rotate(x, rt);
                else rotate(y, rt);
            }
            rotate(x, rt);
        }
    }
    inline void ins(int &x, int lst, int p) {
        if(!x) {
            x = ++siz; fa[x] = lst; ch[x][0] = ch[x][1] = 0; sz[x] = 1;
            val[x] = p; s[x] = 1;
            return;
        }
        if(p == val[x]) {
            s[x] ++; sz[x] ++;
            return ;
        }
        if(p < val[x]) ins(ch[x][0], x, p);
        else ins(ch[x][1], x, p);
        up(x);
    }
    inline void INS(int p) {
        ins(rt, 0, p);
        splay(siz, rt);
    }
    
    inline int find(int x, int p) {
        if(!x) return inf;
        if(val[x] == p) return x;
        if(p < val[x]) return find(ch[x][0], p);
        else return find(ch[x][1], p);
    }
    
    
    inline int gpre(int x, int p) {
        if(!x) return inf;
        if(val[x] < p) {
            int y = gpre(ch[x][1], p);
            if(y != inf) return y;
            else return x;
        } else return gpre(ch[x][0], p);
    }
    inline int gsuf(int x, int p) {
        if(!x) return inf;
        if(val[x] > p) {
            int y = gsuf(ch[x][0], p);
            if(y != inf) return y;
            else return x;
        } else return gsuf(ch[x][1], p);
    }
    
    inline int pre(int x) {
        while(ch[x][1]) x = ch[x][1];
        return x;
    }
    inline int suf(int x) {
        while(ch[x][0]) x = ch[x][0];
        return x;
    }
    
    inline void DEL(int p) {
        int x = find(rt, p); 
        splay(x, rt);
        if(s[x] > 1) {
            --s[x]; up(x);
            return ;
        }
        int y = pre(ch[x][0]); splay(y, ch[x][0]);
        rt = y; fa[y] = 0; ch[y][1] = ch[x][1]; fa[ch[x][1]] = y;
        up(y); fa[x] = ch[x][0] = ch[x][1] = s[x] = sz[x] = 0;
    }
    
    inline void PRE(int p) {
        int x = find(rt, p);
        if(x == inf) {
            int y = gpre(rt, p);
            splay(y, rt); 
            printf("%d\n", val[y]);
            return ;
        }
        splay(x, rt);
        int y = pre(ch[x][0]);
        printf("%d\n", val[y]);
    }
    
    inline void SUF(int p) {
        int x = find(rt, p);
        if(x == inf) {
            int y = gsuf(rt, p);
            splay(y, rt);
            printf("%d\n", val[y]);
            return ;
        }
        splay(x, rt);
        int y = suf(ch[x][1]);
        printf("%d\n", val[y]);
    }
    
    inline void getrank(int p) {
        int x = find(rt, p); splay(x, rt);
        printf("%d\n", sz[ch[x][0]]);
    }
    
    inline int findrk(int x, int p) {
        if(sz[ch[x][0]] + 1 <= p && p <= sz[ch[x][0]] + s[x]) return x;
        if(sz[ch[x][0]] + 1 > p) return findrk(ch[x][0], p);
        else return findrk(ch[x][1], p - s[x] - sz[ch[x][0]]);
    }
    
    inline void prank(int x) {
        int y = findrk(rt, x+1); splay(y, rt);
        printf("%d\n", val[y]);
    }
}T;
     

int main() {
    int Q, op, x; cin >> Q; T.set();
    while(Q--) {
        scanf("%d%d", &op, &x);
        if(op == 1) T.INS(x);
        else if(op == 2) T.DEL(x);
        else if(op == 3) T.getrank(x);
        else if(op == 4) T.prank(x);
        else if(op == 5) T.PRE(x);
        else T.SUF(x);
    }
    return 0;
}
View Code

 

posted @ 2017-07-16 11:12  Galaxies  阅读(244)  评论(0编辑  收藏  举报