zoukankan      html  css  js  c++  java
  • 替罪羊树模版 普通平衡树

    替罪羊树,代码贼长,我哭了。。。

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn = 1e5+5;
    const double alpha = 0.75;
    struct node{
      int l,r,val;
      int size,fact;
      ///子树大小,实际大小
      bool exist;
    }tzy[maxn];
    int cnt,root;
    ///新建节点
    void newnode(int &now,int val)
    {
        now=++cnt;
        tzy[now].val=val;
        tzy[now].size=tzy[now].fact=1;
        tzy[now].exist=true;
    }
    ///判断是否平衡
    bool imbalance(int now)
    {
        ///左右子树的size中最大的一个的大小大于节点大小*平衡因子
        ///被删掉的节点个数大于0.3
        if(max(tzy[tzy[now].l].size,tzy[tzy[now].r].size)>tzy[now].size*alpha
           || tzy[now].size-tzy[now].fact>tzy[now].size*0.3)
            return true;
         else
            return false;
    }
    vector<int>v;
    ///中序列遍历
    void idr(int now)
    {
        if (!now)return;
        idr(tzy[now].l);
        if (tzy[now].exist)
            v.push_back(now);
        idr(tzy[now].r);
    }
    ///拎起来
    void lift(int l,int r,int &now)
    {
        ///拎起来到叶子节点
        if (l==r)
        {
            now=v[l];
            ///变成叶子节点状态
            tzy[now].l=tzy[now].r=0;
            tzy[now].size=tzy[now].fact=1;
            return;
        }
        int m=(l+r)>>1;
        ///防止值相同跑到左边去
        while(m && l<m && tzy[v[m]].val==tzy[v[m-1]].val)
            m--;
        now=v[m];
        if(l<m)lift(l,m-1,tzy[now].l);
        else tzy[now].l=0;
        ///向下取整,可以直接取
        lift(m+1,r,tzy[now].r);
        tzy[now].size=tzy[tzy[now].l].size+tzy[tzy[now].r].size+1;
        tzy[now].fact=tzy[tzy[now].l].fact+tzy[tzy[now].r].fact+1;
    }
    void update(int now,int end)
    {
        if(!now)return;
        if (tzy[end].val<tzy[now].val)
            update(tzy[now].l,end);
        else update(tzy[now].r,end);
        tzy[now].size=tzy[tzy[now].l].size+tzy[tzy[now].r].size+1;
    }
    ///暴力重构
    ///进行中序遍历拉成直线,挂起来,然后分治拎起来
    void rebuild(int &now)
    {
        v.clear();
        idr(now);
        if (v.empty())
        {
            now=0;
            return;
        }
        lift(0,v.size()-1,now);
    }
    ///检查是否需要重构
    ///不能从下往上找
    ///重构条件----当前节点的左子树或者右子树的大小大于当前节点的大小乘以一个平衡因子alpha
    void check(int &now,int end)
    {
        if (now==end)return;
        ///判断当前节点是否平衡
        if (imbalance(now))
        {
            ///重构
            rebuild(now);
            ///往上更新
            update(root,now);
            return ;
        }
        ///终点在当前节点的左子树
        if (tzy[end].val<tzy[now].val)
            check(tzy[now].l,end);
        else
            check(tzy[now].r,end);
    }
    ///插入操作
    void ins(int &now,int val){
        if (!now)//当前节点不存在
        {
            newnode(now,val);;
            ///是否需要重构
            check(root,now);
            return;
        }
        tzy[now].size++;
        tzy[now].fact++;
        ///小于左插,大于右插
        if(val<tzy[now].val)
            ins(tzy[now].l,val);
        else
            ins(tzy[now].r,val);
    }
    ///惰性删除
    void del(int now,int val)
    {
        ///当前节点存在,并且当前节点的值等于当前需要删除的值
        if (tzy[now].exist && tzy[now].val==val)
        {
            tzy[now].exist=false;
            tzy[now].fact--;
            ///删除后是否平衡
            check(root,now);
            return;
        }
        tzy[now].fact--;
        if (val<tzy[now].val)
            del(tzy[now].l,val);
        else
            del(tzy[now].r,val);
    }
    int getrank(int val)
    {
        int now=root,rank=1;
        while(now)
        {
            ///如果查找的值小于等于当前节点的值,往左找
            if (val<=tzy[now].val)
                now=tzy[now].l;
            else
            {
                ///把左子树以及当前节点的值算进去
               rank+=tzy[now].exist+tzy[tzy[now].l].fact;
               now=tzy[now].r;
            }
         //   cout<<tzy[now].val<<" "<<rank<<endl;
        }
       // cout<<endl;
        return rank;
    }
    int getnum(int rank)
    {
        int now=root;
        while(now)
        {
            ///当前节点左子树+当前节点是否存在为rank,那么退出
            if(tzy[now].exist && tzy[tzy[now].l].fact+tzy[now].exist==rank)
                break;
            else if(tzy[tzy[now].l].fact>=rank)
                now=tzy[now].l;
            else
            {
                rank-=tzy[tzy[now].l].fact+tzy[now].exist;
                now=tzy[now].r;
            }
        }
        return tzy[now].val;
    }
    int main(){
       int t;
       int op,x;
       scanf("%d",&t);
       cnt=0;
       while(t--){
          scanf("%d%d",&op,&x);
          if (op==1){
            ins(root,x);
          }else if (op==2){
            del(root,x);
          }else if (op==3){
            printf("%d
    ",getrank(x));
          }else if (op==4){
            printf("%d
    ",getnum(x));
          }else if (op==5){
            ///查询的是x的排名-1的数是什么
            printf("%d
    ",getnum(getrank(x)-1));
          }else {
            ///查询的是小于等于x+1的数的个数
            ///因为我们在查找的时候强行把这个值rank值自动设置为1
            ///那么就强行认为这个数是rank1,然后查询比这个数小的个数
            printf("%d
    ",getnum(getrank(x+1)));
          }
       }
       return 0;
    }
    /*
    5
    1 2
    1 4
    1 6
    6 4
    */

    #include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>using namespace std;const int maxn = 1e5+5;const double alpha = 0.75;struct node{  int l,r,val;  int size,fact;  ///子树大小,实际大小  bool exist;}tzy[maxn];int cnt,root;///新建节点void newnode(int &now,int val){    now=++cnt;    tzy[now].val=val;    tzy[now].size=tzy[now].fact=1;    tzy[now].exist=true;}///判断是否平衡bool imbalance(int now){    ///左右子树的size中最大的一个的大小大于节点大小*平衡因子    ///被删掉的节点个数大于0.3    if(max(tzy[tzy[now].l].size,tzy[tzy[now].r].size)>tzy[now].size*alpha       || tzy[now].size-tzy[now].fact>tzy[now].size*0.3)        return true;     else        return false;}vector<int>v;///中序列遍历void idr(int now){    if (!now)return;    idr(tzy[now].l);    if (tzy[now].exist)        v.push_back(now);    idr(tzy[now].r);}///拎起来void lift(int l,int r,int &now){    ///拎起来到叶子节点    if (l==r)    {        now=v[l];        ///变成叶子节点状态        tzy[now].l=tzy[now].r=0;        tzy[now].size=tzy[now].fact=1;        return;    }    int m=(l+r)>>1;    ///防止值相同跑到左边去    while(m && l<m && tzy[v[m]].val==tzy[v[m-1]].val)        m--;    now=v[m];    if(l<m)lift(l,m-1,tzy[now].l);    else tzy[now].l=0;    ///向下取整,可以直接取    lift(m+1,r,tzy[now].r);    tzy[now].size=tzy[tzy[now].l].size+tzy[tzy[now].r].size+1;    tzy[now].fact=tzy[tzy[now].l].fact+tzy[tzy[now].r].fact+1;}void update(int now,int end){    if(!now)return;    if (tzy[end].val<tzy[now].val)        update(tzy[now].l,end);    else update(tzy[now].r,end);    tzy[now].size=tzy[tzy[now].l].size+tzy[tzy[now].r].size+1;}///暴力重构///进行中序遍历拉成直线,挂起来,然后分治拎起来void rebuild(int &now){    v.clear();    idr(now);    if (v.empty())    {        now=0;        return;    }    lift(0,v.size()-1,now);}///检查是否需要重构///不能从下往上找///重构条件----当前节点的左子树或者右子树的大小大于当前节点的大小乘以一个平衡因子alphavoid check(int &now,int end){    if (now==end)return;    ///判断当前节点是否平衡    if (imbalance(now))    {        ///重构        rebuild(now);        ///往上更新        update(root,now);        return ;    }    ///终点在当前节点的左子树    if (tzy[end].val<tzy[now].val)        check(tzy[now].l,end);    else        check(tzy[now].r,end);}///插入操作void ins(int &now,int val){    if (!now)//当前节点不存在    {        newnode(now,val);;        ///是否需要重构        check(root,now);        return;    }    tzy[now].size++;    tzy[now].fact++;    ///小于左插,大于右插    if(val<tzy[now].val)        ins(tzy[now].l,val);    else        ins(tzy[now].r,val);}///惰性删除void del(int now,int val){    ///当前节点存在,并且当前节点的值等于当前需要删除的值    if (tzy[now].exist && tzy[now].val==val)    {        tzy[now].exist=false;        tzy[now].fact--;        ///删除后是否平衡        check(root,now);        return;    }    tzy[now].fact--;    if (val<tzy[now].val)        del(tzy[now].l,val);    else        del(tzy[now].r,val);}int getrank(int val){    int now=root,rank=1;    while(now)    {        ///如果查找的值小于等于当前节点的值,往左找        if (val<=tzy[now].val)            now=tzy[now].l;        else        {            ///把左子树以及当前节点的值算进去           rank+=tzy[now].exist+tzy[tzy[now].l].fact;           now=tzy[now].r;        }     //   cout<<tzy[now].val<<" "<<rank<<endl;    }   // cout<<endl;    return rank;}int getnum(int rank){    int now=root;    while(now)    {        ///当前节点左子树+当前节点是否存在为rank,那么退出        if(tzy[now].exist && tzy[tzy[now].l].fact+tzy[now].exist==rank)            break;        else if(tzy[tzy[now].l].fact>=rank)            now=tzy[now].l;        else        {            rank-=tzy[tzy[now].l].fact+tzy[now].exist;            now=tzy[now].r;        }    }    return tzy[now].val;}int main(){   int t;   int op,x;   scanf("%d",&t);   cnt=0;   while(t--){      scanf("%d%d",&op,&x);      if (op==1){        ins(root,x);      }else if (op==2){        del(root,x);      }else if (op==3){        printf("%d ",getrank(x));      }else if (op==4){        printf("%d ",getnum(x));      }else if (op==5){        ///查询的是x的排名-1的数是什么        printf("%d ",getnum(getrank(x)-1));      }else {        ///查询的是小于等于x+1的数的个数        ///因为我们在查找的时候强行把这个值rank值自动设置为1        ///那么就强行认为这个数是rank1,然后查询比这个数小的个数        printf("%d ",getnum(getrank(x+1)));      }   }   return 0;}/*51 21 41 66 4*/

    有不懂欢迎咨询 QQ:1326487164(添加时记得备注)
  • 相关阅读:
    CentOS7 FTP安装与配置
    EF CodeFirst 数据库的操作
    CentOS7 防火墙(firewall)的操作命令
    小程序学习(四)小程序逻辑层之注册页面
    小程序学习(三)小程序逻辑层的注册程序和场景值
    小程序学习(二)基本结构与文件的类型
    VS2015 无法启动IIS Express Web服务器(已解决)
    django 2.接口之工作原理
    django 1.开发接口环境搭建
    pytest 15 fixture之autouse=True
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11405323.html
Copyright © 2011-2022 走看看