Scapegoat_Tree模板和splay模板

#define N (100000+10)
const double alpha=0.75;
struct Node
{
    Node *ch[2];
    int key,size,cover;// size为有效节点的数量,cover为节点总数量
    bool exist;// 是否存在(即是否被删除) 
    void push_up()
    {
        size=ch[0]->size+ch[1]->size+(int)exist;
        cover=ch[0]->cover+ch[1]->cover+1;
    }
    bool isBad()
    {
        return ((ch[0]->cover>cover*alpha+5)||(ch[1]->cover>cover*alpha+5));
    }
};
struct Scapegoat_Tree
{
    Node mem_poor[N];//内存池,直接分配好避免动态分配内存占用时间 
    Node *tail,*root,*null;// 用null表示NULL的指针更方便,tail为内存分配指针,root为根 
    Node *bc[N];// 储存被删除的节点的内存地址,分配时可以再利用这些地址
    int bc_top;
    Node *New_Node(int key)
    {
        Node *p=bc_top?bc[--bc_top]:tail++;
        p->ch[0]=p->ch[1]=null;
        p->size=p->cover=1,p->exist=true;
        p->key=key;
        return p;
    }
    void Travel(Node *p,vector<Node*>&v)
    {
        if (p==null) return;
        Travel(p->ch[0],v);
        if (p->exist) v.push_back(p);
        else bc[bc_top++]=p;
        Travel(p->ch[1],v);
    }
    Node *Divide(vector<Node*>&v,int l,int r)
    {
        if (l>=r) return null;
        int mid=l+r>>1;
        Node *p=v[mid];
        p->ch[0]=Divide(v,l,mid);
        p->ch[1]=Divide(v,mid+1,r);
        p->push_up();// 自底向上维护,先维护子树 
        return p;
    }
    void Rebuild(Node *&p)
    {
        static vector <Node*>v;
        v.clear();
        Travel(p,v);
        p=Divide(v,0,v.size());
    }
    Node **Insert(Node *&p,int val)
    {
        if (p==null) 
        {
            p=New_Node(val);
            return &null;
        }
        else
        {
            p->size++;
            p->cover++;
            // 返回值储存需要重构的位置,若子树也需要重构,本节点开始也需要重构,以本节点为根重构 
            Node **res=Insert(p->ch[val>=p->key],val);
            if (p->isBad()) res=&p;
            return res;
        }
    }
    void Erase(Node *p,int id)
    {
        p->size--;
        int offset=p->ch[0]->size+p->exist;
        if (p->exist&&id==offset)
        {
            p->exist=false;
            return;
        }
        else
        {
            if (id<=offset) Erase(p->ch[0],id);
            else Erase(p->ch[1],id-offset);
        }
    }
    void Init() 
    {
        tail=mem_poor;
        null=tail++;
        null->ch[0]=null->ch[1]=null;
        null->cover=null->size=null->key=0;
        root=null;
        bc_top=0;
    }
    void Insert(int val)
    {
        Node **p=Insert(root,val);
        if (*p!=null) Rebuild(*p);
    }
    int Rank(int val)
    {
        Node *now=root;
        int ans=1;
        while (now!=null)
        { // 非递归求排名 
            if (now->key>=val) now=now->ch[0];
            else
            {
                ans+=now->ch[0]->size+now->exist;
                now=now->ch[1];
            }
        }
        return ans;
    }
    int Kth(int k)
    {
        Node *now=root;
        while (now!=null)
        { // 非递归求第K大 
            if (now->ch[0]->size+1==k&&now->exist) return now->key;
            else if (now->ch[0]->size>=k) now=now->ch[0];
            else k-=now->ch[0]->size+now->exist,now=now->ch[1];
        }
    }
    void Erase(int k)
    {
        Erase(root,Rank(k));
        if (root->size<alpha*root->cover) Rebuild(root);
    }
    void Erase_kth(int k)
    {
        Erase(root, k);
        if (root->size<alpha*root->cover) Rebuild(root);
    }
}stree;

struct Node
{
    int key,sz,cnt;
    int ch[2],pnt;
    Node(){}
    Node(int x,int y,int z)
    {
        key=x,sz=y,cnt=z;
    }
}a[N<<1];
int root,ncnt;
void rs(int x)
{
    a[x].sz=a[a[x].ch[0]].sz+a[a[x].ch[1]].sz+a[x].cnt;
}
void rotate(int x,bool d)
{
    int y=a[x].pnt;
    a[y].ch[!d]=a[x].ch[d];
    if (a[x].ch[d]!=0) a[a[x].ch[d]].pnt=y;
    a[x].pnt=a[y].pnt;
    if (a[y].pnt!=0)
    {
        if (y==a[a[y].pnt].ch[d]) a[a[y].pnt].ch[d]=x;
        else a[a[y].pnt].ch[!d]=x;
    }
    a[x].ch[d]=y;
    a[y].pnt=x;
    rs(y);
    rs(x);
}
void splay(int x,int target)
{
    int y;
    while (a[x].pnt!=target)
    {
        y=a[x].pnt;
        if (x==a[y].ch[0])
        {
            if (a[y].pnt!=target&&y==a[a[y].pnt].ch[0])
				rotate(y,true);
            rotate(x,true);
        }
        else
        {
            if (a[y].pnt!=target&&y==a[a[y].pnt].ch[1])
				rotate(y,false);
            rotate(x,false);
        }
    }
    if (target==0) root=x;
}
void Insert(int key,int now,int number)
{
    if (root==0)
    {
        root=now?now:(++ncnt);
        a[root].ch[0]=a[root].ch[1]=a[root].pnt=0;
        a[root].key=key;
        a[root].sz=a[root].cnt=number;
        return;
    }
    int x=root,y;
    while (1)
    {
        a[x].sz+=number;
        if (key==a[x].key)
        {
            a[x].cnt+=number;
            a[x].sz+=number;
            rs(x);
            y=x;
            break;
        }
        else
            if (key<a[x].key)
            {
                if (a[x].ch[0]!=0) x=a[x].ch[0];
                else
                {
                    a[x].ch[0]=now?now:(++ncnt);
                    y=a[x].ch[0];
                    a[y].key=key;
                    a[y].sz=a[y].cnt=number;
                    a[y].ch[0]=a[y].ch[1]=0;
                    a[y].pnt=x;
                    break;
                }
            }
            else
            {
                if (a[x].ch[1]!=0) x=a[x].ch[1];
                else
                {
                    a[x].ch[1]=now?now:(++ncnt);
                    y=a[x].ch[1];
                    a[y].key=key;
                    a[y].sz=a[y].cnt=number;
                    a[y].ch[0]=a[y].ch[1]=0;
                    a[y].pnt=x;
                    break;
                }
            }
    }
    splay(y,0);
}
int searchmin(int x)
{
    int y=a[x].pnt;
    while (a[x].ch[0]!=0) x=a[x].ch[0];
    splay(x,y);
    return x;
}
int search(int key)
{
    if (root==0) return 0;
    int x=root,y=0;
    while (1)
    {
        if (key==a[x].key) break;
        else
            if (key>a[x].key)
            {
                if (a[x].ch[1]!=0) x=a[x].ch[1];
                else break;
            }
            else
            {
                if (a[x].ch[0]!=0) x=a[x].ch[0];
                else break;
            }
    }
    y=x;
    splay(x,0);
    return y;
}
int Erase(int key,int number)
{
    if (root==0) return 0;
    int x=search(key),y;
    if (x==0) return 0;
    if (a[x].cnt>number)
    {
        a[x].cnt-=number;
        a[x].sz-=number;
        rs(x);
        return 0;
    }
    else
        if (a[x].ch[0]==0&&a[x].ch[1]==0)
        {
            root=0;
            return x;
        }
        else
            if (a[x].ch[0]==0)
            {
                root=a[x].ch[1];
                a[a[x].ch[1]].pnt=0;
                return x;
            }
            else
                if (a[x].ch[1]==0)
                {
                    root=a[x].ch[0];
                    a[a[x].ch[0]].pnt=0;
                    return x;
                }
    y=searchmin(a[x].ch[1]);
    a[y].pnt=0;
    a[y].ch[0]=a[x].ch[0];
    a[a[x].ch[0]].pnt=y;
    rs(y);
    root=y;
    return x;
}
int qry_kth(int x,int y)
{
    int now=root;
    while (now)
    {
        if (a[a[now].ch[0]].sz>=x) now=a[now].ch[0];
        else 
        {
        	if (a[a[now].ch[0]].sz+a[now].cnt<x)
			{
				x-=a[a[now].ch[0]].sz+a[now].cnt;
				now=a[now].ch[1];
			}
	        else break;
		}
    }
    return a[now].key;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值