洛谷P3369【模板】普通平衡树

\(fhq-treap\)实现。

正文部分

\(fhq-treap\)的所有操作都在两个\(split\)的基础上,一次\(val\),一次\(size\)
注意:这里我们是将小于等于操作数的值分为一棵树,其余分为另一棵树
分离和合并的过程很简单,学的话可以看我的代码手动模拟一下,这个过程应该不是很难。
对于一个数\(x\)的插入,我们先已这个值分一次\(val\),然后创建新节点和并即可。
对于一个数\(x\)的删除,我们先已\(x\)分一次\(val\),然后在分出来的左子树里已\(x-1\)分一次\(val\),最后产生的右子树我们将其左右孩子合并即可。
对于一个数\(x\)的排名,我们将其以\(x-1\)分一次\(val\),然后输出左子树的\(size+1\)即可
对于找到排名为\(x\)的数,我们直接求一次\(kth\)就好了
对于求\(x\)的前驱,我们将其已\(x-1\)分一次\(val\),然后在左子树里找到\(kth\)为左子树的\(size\)的节点就好了
对于求\(x\)的后续,我们已\(x\)分一次\(val\),然后在右子树里找到\(kth\)\(1\)的节点即可

My Code:

#include <bits/stdc++.h>
#define il inline
#define temp template<class T>
const int MAXN = 1e5 + 10;
using namespace std;
temp il void rd(T& res) {
    res = 0;char c;bool sign = 0;
    for(c = getchar();!isdigit(c);c = getchar()) sign |= c == '-';
    for(;isdigit(c);c = getchar()) res = (res << 1) + (res << 3) + (c ^ 48);
    (sign) && (res = -res);
    return; 
}
struct TreeNode {
    int ch[2],size,val,rnd;           
}tr[MAXN];
int n,m,i,j,k,q,cnt,root,y,z;
il int NewNode(int v) {
    tr[++cnt].size = 1;
    tr[cnt].val = v;tr[cnt].rnd = rand();
    return cnt;
}
il void pushup(int o) {
    tr[o].size = tr[tr[o].ch[0]].size + tr[tr[o].ch[1]].size + 1;
    return;
}
int merge(int u,int v) {
    if(!u) return v;if(!v) return u;
    if(tr[u].rnd < tr[v].rnd) {
        tr[u].ch[1] = merge(tr[u].ch[1],v);
        pushup(u);
        return u;
    } else {
        tr[v].ch[0] = merge(u,tr[v].ch[0]);
        pushup(v);
        return v;
    }
}
void split_v(int now,int k,int& x,int& y) {
    if(!now) x = y = 0;
    else {
        if(tr[now].val <= k) x = now,split_v(tr[now].ch[1],k,tr[now].ch[1],y);
        else y = now,split_v(tr[now].ch[0],k,x,tr[now].ch[0]);
        pushup(now);
    }   
    return;
}
il int kth(int u,int k) {
    while(1) {
        if(k <= tr[tr[u].ch[0]].size) {
            u = tr[u].ch[0];
        } else {
            if(k == tr[tr[u].ch[0]].size + 1) return u;
            k -= tr[tr[u].ch[0]].size + 1;u = tr[u].ch[1];
        }
    }
}
int main() {
    srand((unsigned)time(NULL));
    rd(q);
    while(q--) {
        int opt,x;rd(opt);rd(x);
        if(opt == 1) {
            split_v(root,x,y,z);
            root = merge(merge(y,NewNode(x)),z);
        } else if(opt == 2) {
            int k;
            split_v(root,x,y,k);
            split_v(y,x - 1,y,z);
            z = merge(tr[z].ch[0],tr[z].ch[1]);
            root = merge(y,merge(z,k)); 
        } else if(opt == 3) {
            split_v(root,x - 1,y,z);
            printf("%d\n",tr[y].size + 1);
            root = merge(y,z);      
        } else if(opt == 4) {
            printf("%d\n",tr[kth(root,x)].val);    
        } else if(opt == 5) {
            split_v(root,x - 1,y,z);        
            printf("%d\n",tr[kth(y,tr[y].size)].val);    
            root = merge(y,z);    
        } else {
            split_v(root,x,y,z);
            printf("%d\n",tr[kth(z,1)].val);
            root = merge(y,z);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Sai0511/p/10360677.html