模板:替罪羊树

一种平衡树,暴力重构,发现不平衡就重新建树

感谢小红指出我的错误,改完之后发现。。。时间变成了原来的两倍。。。

人丑自带大常数

那么粘一个小红的代码吧,我的时间实在是不太乐观

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const double al=0.7;
struct node
{
    node *l,*r;
    int val,size,cnt;
    bool del;
    bool bad()
    {
        return l->cnt>al*cnt+5||r->cnt>al*cnt+5;
    }
    void up()
    {
        size=!del+l->size+r->size;
        cnt=1+l->cnt+r->cnt;
    }
};
node *null,**badtag;
void dfs(node *k,vector<node*> &v)
{
    if(k==null)return ;
    dfs(k->l,v);
    if(!k->del)v.push_back(k);
    dfs(k->r,v);
    if(k->del)delete k;
}
node *build(vector<node*> &v,int l,int r)
{
    if(l>=r)return null;
    int mid=l+r>>1;
    node *k=v[mid];
    k->l=build(v,l,mid);
    k->r=build(v,mid+1,r);
    k->up();
    return k;
}
void rebuild(node* &k)
{
    vector<node*> v;
    dfs(k,v);
    k=build(v,0,v.size());
}
void insert(int x,node* &k)
{
    if(k==null)
    {
        k=new node;
        k->l=k->r=null;
        k->del=0;
        k->size=k->cnt=1;
        k->val=x;
        return ;
    }
    else
    {
        ++k->size;++k->cnt;
        if(x>=k->val)insert(x,k->r);
        else insert(x,k->l);
        if(k->bad())badtag=&k;
        else if(badtag!=&null)
            k->cnt-=(*badtag)->cnt-(*badtag)->size;
    }
}
void ins(int x,node* &k)
{
    badtag=&null;
    insert(x,k);
    if(badtag!=&null)rebuild(*badtag);
}
int getrk(node *now,int x)
{
    int ans=1;
    while(now!=null)
    {
        if(now->val>=x)now=now->l;
        else
        {
            ans+=now->l->size+!now->del;
            now=now->r;
        }
    }
    return ans;
}
int kth(node *now,int x)
{
    while(now!=null)
    {
        if(!now->del&&now->l->size+1==x)
            return now->val;
        if(now->l->size>=x)now=now->l;
        else
        {
            x-=now->l->size+!now->del;
            now=now->r;
        }
    }
}
void erase(node *k,int rk)
{
    if(!k->del&&rk==k->l->size+1)
    {
        k->del=1;
        --k->size;
        return ;
    }
    --k->size;
    if(rk<=k->l->size+!k->del)erase(k->l,rk);
    else erase(k->r,rk-k->l->size-!k->del);
}
node *root;int n;
int main()
{
    null=new node;
    root=null;
    scanf("%d",&n);
    while(n--)
    {
        int op,x;
        scanf("%d%d",&op,&x);
        switch(op)
        {
            case 1:ins(x,root);break;
            case 2:erase(root,getrk(root,x));break;
            case 3:printf("%d\n",getrk(root,x));break;
            case 4:printf("%d\n",kth(root,x));break;
            case 5:printf("%d\n",kth(root,getrk(root,x)-1));break;
            case 6:printf("%d\n",kth(root,getrk(root,x+1)));break;
        }
    }
    return 0;
}

算了还是粘一个自己的700ms代码:

#include <vector>
#include <iostream>
#include <cstdio>
using namespace std;
const double alpha = 0.75;
int n, opt, x;
struct node {
    node *ls, *rs;
    int val, size, cnt;
    bool deleted;
    bool isbad() { return ls->cnt > alpha * cnt + 5 || rs->cnt > alpha * cnt + 5; }
    void maintain() {
        size = !deleted + ls->size + rs->size;
        cnt = 1 + ls->cnt + rs->cnt;
    }
} * null, *root, **badtag;
struct ScapeGoat_Tree {
private:
    void dfs(node *k, vector<node *> &v) {
        if (k == null)
            return;
        dfs(k->ls, v);
        if (!k->deleted)
            v.push_back(k);
        dfs(k->rs, v);
        if (k->deleted)
            delete k;
    }
    node *build(vector<node *> &v, int l, int r) {
        if (l >= r)
            return null;
        int mid = (l + r) >> 1;
        node *k = v[mid];
        k->ls = build(v, l, mid);
        k->rs = build(v, mid + 1, r);
        k->maintain();
        return k;
    }
    void rebuild(node *&k) {
        vector<node *> v;
        dfs(k, v);
        k = build(v, 0, v.size());
    }

public:
    void insert(int x, node *&k) {
        badtag = &null;
        if (k == null) {
            k = new node;
            k->ls = k->rs = null;
            k->deleted = false;
            k->size = k->cnt = 1;
            k->val = x;
            return;
        } else {
            ++k->size;
            ++k->cnt;
            if (x >= k->val)
                insert(x, k->rs);
            else
                insert(x, k->ls);
            if (k->isbad())
                badtag = &k;
            else if (badtag == &null)
                k->cnt -= (*badtag)->cnt - (*badtag)->size;
        }
        if (badtag != &null)
            rebuild(*badtag);
    }
    int get_rank(node *k, int x) {
        int ans = 1;
        while (k != null) {
            if (k->val >= x)
                k = k->ls;
            else {
                ans += k->ls->size + !k->deleted;
                k = k->rs;
            }
        }
        return ans;
    }
    int get_kth(node *k, int x) {
        while (k != null) {
            if (!k->deleted && k->ls->size + 1 == x)
                return k->val;
            if (k->ls->size >= x)
                k = k->ls;
            else {
                x -= k->ls->size + !k->deleted;
                k = k->rs;
            }
        }
    }
    void erase(node *k, int rk) {
        if (!k->deleted && rk == k->ls->size + 1) {
            k->deleted = 1;
            --k->size;
            return;
        }
        --k->size;
        if (rk <= k->ls->size + !k->deleted)
            erase(k->ls, rk);
        else
            erase(k->rs, rk - k->ls->size - !k->deleted);
    }
} SGT;
int main() {
    null = new node;
    root = null;
    scanf("%d", &n);
    while (n--) {
        scanf("%d%d", &opt, &x);
        if (opt == 1)
            SGT.insert(x, root);
        else if (opt == 2)
            SGT.erase(root, SGT.get_rank(root, x));
        else if (opt == 3)
            printf("%d\n", SGT.get_rank(root, x));
        else if (opt == 4)
            printf("%d\n", SGT.get_kth(root, x));
        else if (opt == 5)
            printf("%d\n", SGT.get_kth(root, SGT.get_rank(root, x) - 1));
        else if (opt == 6)
            printf("%d\n", SGT.get_kth(root, SGT.get_rank(root, x + 1)));
    }
}

以普通平衡树为例:

#include<vector>
#include<iostream>
#include<cstdio>
using namespace std;
const double alpha=0.75;
int n,opt,x;
struct node{
    node *ls,*rs;
    int val,size,cnt;
    bool deleted;
    bool isbad(){
		return ls->cnt>alpha*cnt+5||rs->cnt>alpha*cnt+5;
	}
    void maintain(){
		size=!deleted+ls->size+rs->size;
		cnt=1+ls->cnt+rs->cnt;
	}
}*null,*root;
struct ScapeGoat_Tree{
	private:
		void dfs(node *k,vector<node*> &v){
			if(k==null) return;
			dfs(k->ls,v);
			if(!k->deleted) v.push_back(k);
			dfs(k->rs,v);
			if(k->deleted) delete k;
		}
		node *build(vector<node*> &v,int l,int r){
			if(l>=r) return null;
			int mid=(l+r)>>1;
			node *k=v[mid];
			k->ls=build(v,l,mid);
			k->rs=build(v,mid+1,r);
			k->maintain();
			return k;
		}
		void rebuild(node* &k){
			vector<node*>v;
			dfs(k,v);
			k=build(v,0,v.size());
		}
	public:
		void insert(int x,node* &k){
			if(k==null){
				k=new node;
				k->ls=k->rs=null;
				k->deleted=false;
				k->size=k->cnt=1;
				k->val=x;
				return;
			}else{
				++k->size;
				++k->cnt;
				if(x>=k->val)
				    insert(x,k->rs);
				else insert(x,k->ls);
				if(k->isbad())rebuild(k);
			}
		}
		int get_rank(node *k,int x){
			int ans=1;
			while(k!=null){
				if(k->val>=x) k=k->ls;
				else{
				    ans+=k->ls->size+!k->deleted;
				    k=k->rs;
				}
			}
			return ans;
		}
		int get_kth(node *k,int x){
			while(k!=null){
				if(!k->deleted && k->ls->size+1==x)
				    return k->val;
				if(k->ls->size>=x) k=k->ls;
				else{
				    x-=k->ls->size+!k->deleted;
				    k=k->rs;
				}
			}
		}
		void erase(node *k,int rk){
			if(!k->deleted && rk==k->ls->size+1){
				k->deleted=1;
				--k->size;
				return;
			}
			--k->size;
			if(rk<=k->ls->size+!k->deleted)
				erase(k->ls,rk);
			else erase(k->rs,rk-k->ls->size-!k->deleted);
		}
}SGT;
int x1,y1;
int main(){
    null=new node;
    root=null;
    scanf("%d",&n);
    while(n--){
        scanf("%d%d",&opt,&x);
        if(opt==1) SGT.insert(x,root);
        else if(opt==2) SGT.erase(root,SGT.get_rank(root,x));
        else if(opt==3) printf("%d\n",SGT.get_rank(root,x));
        else if(opt==4) printf("%d\n",SGT.get_kth(root,x));
        else if(opt==5) printf("%d\n",SGT.get_kth(root,SGT.get_rank(root,x)-1));
        else if(opt==6) printf("%d\n",SGT.get_kth(root,SGT.get_rank(root,x+1)));
    }
}

 

posted @ 2019-08-06 11:59  xukl21  阅读(141)  评论(0编辑  收藏  举报