替罪羊树模版 普通平衡树

允我心安 提交于 2019-11-28 10:39:57

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

#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\n",getrank(x));
      }else if (op==4){
        printf("%d\n",getnum(x));
      }else if (op==5){
        ///查询的是x的排名-1的数是什么
        printf("%d\n",getnum(getrank(x)-1));
      }else {
        ///查询的是小于等于x+1的数的个数
        ///因为我们在查找的时候强行把这个值rank值自动设置为1
        ///那么就强行认为这个数是rank1,然后查询比这个数小的个数
        printf("%d\n",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\n",getrank(x));      }else if (op==4){        printf("%d\n",getnum(x));      }else if (op==5){        ///查询的是x的排名-1的数是什么        printf("%d\n",getnum(getrank(x)-1));      }else {        ///查询的是小于等于x+1的数的个数        ///因为我们在查找的时候强行把这个值rank值自动设置为1        ///那么就强行认为这个数是rank1,然后查询比这个数小的个数        printf("%d\n",getnum(getrank(x+1)));      }   }   return 0;}/*51 21 41 66 4*/

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!