ZJOI2006书架【无旋treap】

这道题相对于普通无旋treap需要多维护一个父亲节点,因为需要找书本编号为S的位置,知道位置就好办了。。

	bool isright(int rt) {
    		return tr[tr[rt].fa].ch[1] == rt;
	 }
	int find(int x) {//如果是右节点,那么左节点的子树个数+1都是序号小于他的。
    int rt = id[x], res = 1 + tr[tr[rt].ch[0]].size;
    while(rt != root && rt) {
        if(isright(rt)) res += tr[tr[tr[rt].fa].ch[0]].size + 1;
        rt = tr[rt].fa;
    }
    return res;
}
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
typedef long long ll;
const ll mod = 1e9+7;
int Case = 1;
int n, m;
struct Treap{
    struct node{
        int size, val, dat;
        int ch[2], fa;
    }tr[maxn];
    int root, tot, id[maxn];
    void pushup(int rt) {
        tr[rt].size = tr[tr[rt].ch[0]].size + tr[tr[rt].ch[1]].size + 1;
        tr[tr[rt].ch[0]].fa = tr[tr[rt].ch[1]].fa = rt;
    }
    int newnode(int v) {
        tot++;
        id[v] = tot;
        tr[tot].size = 1;
        tr[tot].val = v;
        tr[tot].dat = rand();
        return tot;
    }
    bool isright(int rt) {
        return tr[tr[rt].fa].ch[1] == rt;
    }
    int find(int x) {
        int rt = id[x], res = 1 + tr[tr[rt].ch[0]].size;
        while(rt != root && rt) {
            if(isright(rt)) res += tr[tr[tr[rt].fa].ch[0]].size + 1;
            rt = tr[rt].fa;
        }
        return res;
    }
    void spilt(int rt, int k, int &x, int &y) {
        //if(rt == root) printf("%d\n", tr[tr[rt].ch[0]].size);
        if(!rt) x = y = 0;
        else {
            if(tr[tr[rt].ch[0]].size >= k) {
                y = rt;
                spilt(tr[y].ch[0], k, x, tr[y].ch[0]);
                pushup(y);
            }
            else {
                x = rt;
                spilt(tr[x].ch[1], k-tr[tr[rt].ch[0]].size-1, tr[x].ch[1], y);
                pushup(x);
            }
        }
    }
    int merge(int A, int B) {
        if(!A || !B) return A + B;
        if(tr[A].dat > tr[B].dat) {
            tr[A].ch[1] = merge(tr[A].ch[1], B);
            pushup(A);
            return A;
        }
        else {
            tr[B].ch[0] = merge(A, tr[B].ch[0]);
            pushup(B);
            return B;
        }
    }
    void Top(int x) {
        int num = find(x), a, b, c;
        spilt(root, num-1, a, b);
        spilt(b, 1, b, c);
        root = merge(merge(b, a), c);
    }
    void Botton(int x) {
        int num = find(x), a, b, c;
        spilt(root, num-1, a, b);
        spilt(b, 1, b, c);
        root = merge(a, merge(c, b));
    }
    void insert(int s, int t) {
        if(t) {
            if(t == 1) {
                int num = find(s), a, b, c, d;
                spilt(root, num-1, a, b);
                spilt(b, 1, b, c);
                spilt(c, 1, c, d);
                root = merge(merge(a, c), merge(b, d));
            }
            else {
                int num = find(s), a, b, c, d;
                spilt(root, num-2, a, b);
                spilt(b, 1, b, c);
                spilt(c, 1, c, d);
                root = merge(merge(a, c), merge(b, d));
            }
        }
    }
    int ask(int s) {
        return find(s)-1;
    }
    int query(int s) {
        int a, b, c;
        spilt(root, s-1, a, b);
        spilt(b, 1, b, c);
        //printf("qb = %d\n", tr[b].val);
        root = merge(merge(a, b), c);
        return tr[b].val;
    }
    void dfs(int rt) {
        if(!rt) return;
        dfs(tr[rt].ch[0]);
        printf("%d ", tr[rt].val);
        dfs(tr[rt].ch[1]);
    }
}treap;
void solve() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) {
        int val;scanf("%d", &val);
        treap.root = treap.merge(treap.root, treap.newnode(val));
    }
    //treap.dfs(treap.root);
    for(int i = 1; i <= m; i++) {
        char ss[10];scanf("%s", ss);
        int s;scanf("%d", &s);
        if(ss[0] == 'T') treap.Top(s);
        else if(ss[0] == 'B') treap.Botton(s);
        else if(ss[0] == 'I') {
            int t;scanf("%d", &t);
            treap.insert(s, t);
        }
        else if(ss[0] == 'A') printf("%d\n", treap.ask(s));
        else printf("%d\n", treap.query(s));
        //if(ss[0] == 'I') treap.dfs(treap.root);
    }
    return;
}
int main() {
    //g++ -std=c++11 -o2 1.cpp -o f && ./f < in.txt
    //ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt","w",stdout);
#endif
while(Case--) {
    solve();
    }
return 0;
}

只用treap的话也可以做,修改操作其实就是在修改权值,一开始权值是1-n,如果把某个数置顶或置底先通过权值删除,然后把这个数的权值修改为n+1在插入。

猜你喜欢

转载自blog.csdn.net/qq_39921637/article/details/95943337