zoukankan      html  css  js  c++  java
  • [模板] 宗法树

    详解极其优秀的数据结构:宗法树
    其实我写得非常简陋
    代码量小,类似平衡树+线段树的功能(除了LCT都能做),跑得飞快

    网上没找到太多资料,先写一点

    宗法树是这样的一棵二叉树:
    数据存储在叶子里,非叶子存储两个子树的最大值/最小值,左小右大,每个非叶子节点必须有两个叶子

    详解见注释

    //Stay foolish,stay hungry,stay young,stay simple
    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    const int MAXN=100005;
    const int INF=1<<30;
    
    //Patriarchal legal tree
    #define leaf(x) (!(t[x].ch[0]||t[x].ch[1]))
    struct Node{
        int val,size,ch[2];
    }t[MAXN<<2]; 
    int cnt,n,root;
    /*如果空间紧张可以加垃圾回收*/ 
    inline int newnode(int val){t[++cnt].val=val;t[cnt].size=1;return cnt;}
    void pushup(int o){//维护非叶子节点的val(最大值)和size 
        if(leaf(o)) return;
        t[o].val = max(t[t[o].ch[0]].val,t[t[o].ch[1]].val);
        t[o].size = t[t[o].ch[0]].size+t[t[o].ch[1]].size;
    }
    void rotate(int o,int d){//可以看成一个"平行四边形"四顶点的平移 
        int r=t[o].ch[d];//备份 
        t[o].ch[d]=t[o].ch[d^1];//当前节点B侧->节点A侧节点 
        t[t[o].ch[d]].ch[d]=r;//当前节点A侧->当前节点A侧.A侧 
        t[t[o].ch[d]].ch[d^1]=t[t[o].ch[d]].ch[d];//当前节点A侧.A侧->当前节点A侧.B侧 
        t[o].ch[d^1]=t[t[o].ch[d]].ch[d^1];//当前节点A侧.B侧->当前节点B侧 
        pushup(t[o].ch[d]);pushup(t[o].ch[d^1]);
    }
    void maintain(int o){//维护非叶子节点
        if(leaf(o))return;
        if(t[t[o].ch[0]].size>=t[t[o].ch[1]].size<<2) rotate(o,0);
        if(t[t[o].ch[1]].size>=t[t[o].ch[0]].size<<2) rotate(o,1);
    }
    void insert(int &o,int val){
        if(!o){o=newnode(val);return;}//给新点开空间 
        if(leaf(o)){//到达叶子节点 
            t[o].ch[0]=newnode(min(val,t[o].val));//同时插入两个点! 
            t[o].ch[1]=newnode(max(val,t[o].val));//宗法树要求非叶子节点必须两个儿子 
            pushup(o);return;
        }
        val>t[t[o].ch[0]].val?insert(t[o].ch[1],val):insert(t[o].ch[0],val);//否则递归找点 
        pushup(o);
    }
    void del(int o,int fa,int val){
        if(leaf(o)){
            if(t[o].val==val)//找到该点 
                t[fa].ch[0]==o?t[fa]=t[t[fa].ch[1]]:t[fa]=t[t[fa].ch[0]];//用对立兄弟代替父亲实现删除       
            return;//此时兄弟仍为叶子,且满足宗法树定义 
        }
        val>t[t[o].ch[0]].val?del(t[o].ch[1],o,val):del(t[o].ch[0],o,val);//递归找点 
        pushup(o);
    }
    int rnk(int o,int val){
        if(leaf(o)) return val>t[o].val?2:1;
        return val>t[t[o].ch[0]].val?rnk(t[o].ch[1],val)+t[t[o].ch[0]].size:rnk(t[o].ch[0],val);
    }
    int kth(int o,int k){
        if(leaf(o)) return t[o].val;
        return k<=t[t[o].ch[0]].size?kth(t[o].ch[0],k):kth(t[o].ch[1],k-t[t[o].ch[0]].size);
    }
    int main()  {  
        scanf("%d",&n);  
        insert(root,INF);//记得加 
        for (int i=1;i<=n;i++){  
            int opt,x;  
            scanf("%d %d",&opt,&x);  
            if (opt==1) insert(root,x);  
            if (opt==2) del(root,0,x);  
            if (opt==3) printf("%d
    ",rnk(root,x));  
            if (opt==4) printf("%d
    ",kth(root,x));  
            if (opt==5) printf("%d
    ",kth(root,rnk(root,x)-1));  
            if (opt==6) printf("%d
    ",kth(root,rnk(root,x+1)));  
        }  
        return 0;
    }  

    附飞快的读入优化

    
    struct file_io{
        #define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
        char inbuf[1 << 25], *pin, outbuf[1 << 25], *pout;
        int stk[20];
    
        file_io(): pout(outbuf) {fread(pin = inbuf, 1, 1 << 25, stdin);}
        ~file_io() {fwrite(outbuf, 1, pout - outbuf, stdout);}
    
        inline void getint(int &num){
            bool neg = 0; num = 0;
            while(!isdigit(*pin)) if(*pin++ == '-') neg = 1;
            while(isdigit(*pin)) num = num * 10 + *pin++ - '0';
            if(neg) num = -num;
        }
    
        inline void putint(int num){
            static int *v = stk;
            if(!num) *pout++ = '0';
            else{
                if(num < 0) *pout++ = '-', num = -num;
                for(; num; num /= 10) *v++ = num % 10;
                while(v != stk) *pout++ = *--v + '0';
            }
        }
    
        inline void nextline() {*pout++ = '
    ';}
    } fio;
    #define getint(num) fio.getint(num)
    #define putint(num) fio.putint(num)
    #define nextline() fio.nextline()

    本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9247420.html

  • 相关阅读:
    MySQL教程(四)—— MySQL的登录与退出
    MySQL教程(三)—— MySQL的安装与配置
    django中使用POST方法报错 URL via POST, but the URL doesn't end in a slash
    django的html模板中获取字典的值
    使用pycharm手动搭建python语言django开发环境(五) 使用日志模块打日志
    使用pycharm手动搭建python语言django开发环境(四) django中buffer类型与str类型的联合使用
    python语言 buffer类型数据的使用 'ascii' codec can't decode byte 0xe5 问题的解决
    使用pycharm手动搭建python语言django开发环境(三) 使用django的apps应用 添加应用静态文件
    使用pycharm手动搭建python语言django开发环境
    使用pycharm手动搭建python语言django开发环境(一)
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9247420.html
Copyright © 2011-2022 走看看