• 洛谷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
    ",tr[y].size + 1);
                root = merge(y,z);		
            } else if(opt == 4) {
                printf("%d
    ",tr[kth(root,x)].val);    
            } else if(opt == 5) {
                split_v(root,x - 1,y,z);        
                printf("%d
    ",tr[kth(y,tr[y].size)].val);    
                root = merge(y,z);    
            } else {
                split_v(root,x,y,z);
                printf("%d
    ",tr[kth(z,1)].val);
                root = merge(y,z);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    根据当前系统时钟或签名文件的时间戳记核对时,所需要的凭证不在有效期内。
    自定义生成二维码
    MyBatis 开发学习记录
    SPRINGCLOUD 开发学习记录
    DOCKER 开发学习记录
    Spring in action学习笔记
    23种设计模式JAVA 实现目录总结
    访问者模式
    迭代器模式
    简单工厂模式
  • 原文地址:https://www.cnblogs.com/Sai0511/p/10360677.html
Copyright © 2020-2023  润新知