bzoj3224: Tyvj 1728 普通平衡树

就是写替罪羊模版的。

有一件非常恐怖的事情,就是我在ins的时候判是否重建,第7个点就会跑13秒

然后删了就A了!!A了???

upd:我尝试把平衡因子改成0.5也能过,从0.5开始往上加复杂度就逐渐增加。

upd2:发现是递归版本的ins从下往上修改,所以从上往下修改问题就不大了。

upd3:发现现在还是从下往上修改,但是只改一次。有点玄学。

upd:感觉这个东西很不可用啊。。。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const double alpha=0.75;

struct node
{
    int c,son[2],tot,siz,alive;//tot表示管理节点总数(纯属用来判重建)siz表示除去被删除的节点的总数,alive表示该点是否被删 
}tr[210000];int root;
int top,sta[210000];//用于回收空间

int Llen,L[110000];//得出暴力重建的子树的中序遍历 
void gotravel(int x)
{
    if(x==0)return ;
    gotravel(tr[x].son[0]);
    
    if(tr[x].alive==1)L[++Llen]=x;
    else sta[++top]=x;
    
    gotravel(tr[x].son[1]);
}
int build(int l,int r)//重建与值无关,只是改变树的形态 
{
    if(l>r)return 0;
    if(l==r)
    {
        int x=L[l];
        tr[x].son[0]=tr[x].son[1]=0;
        tr[x].tot=tr[x].siz=1;
        return x;
    }
    int mid=(l+r)/2;
    int x=L[mid];
    tr[x].son[0]=build(l,mid-1);
    tr[x].son[1]=build(mid+1,r);
    
    int lc=tr[x].son[0],rc=tr[x].son[1];
    tr[x].tot=tr[lc].tot+tr[rc].tot+1;
    tr[x].siz=tr[lc].siz+tr[rc].siz+1;
    
    return x;
}
void rebuild(int f,int x,int w)
{
    Llen=0;gotravel(x);
    int tt=build(1,Llen);
    if(f!=0)tr[f].son[w]=tt;
    else root=tt;
}//------------rebuild------------------

void add(int f,int d,int w)
{
    int x=sta[top];top--;
    tr[x].c=d;
    tr[x].son[0]=tr[x].son[1]=0;
    tr[x].tot=tr[x].siz=1;
    tr[x].alive=1;
    
    if(f!=0)tr[f].son[w]=x;
    else root=x;
}
int tlen,tmp[110000];
void ins(int d) 
{
    if(root==0)
    {
        add(0,d,0);
        return ;
    }
    
    int x=root;
    tlen=0;tmp[0]=0;tmp[++tlen]=x;
    while(x!=0)
    {
        tr[x].tot++;tr[x].siz++;
        int lc=tr[x].son[0],rc=tr[x].son[1];
        if(d<=tr[x].c)
        {
            if(lc==0){add(x,d,0);break;}
            else x=lc, tmp[++tlen]=x;
        }
        else
        {
            if(rc==0){add(x,d,1);break;}
            else x=rc, tmp[++tlen]=x;
        }
    }
    
    for(int i=tlen;i>=1;i--)
    {
        int x=tmp[i];
        int lc=tr[x].son[0],rc=tr[x].son[1];
        if( (double(tr[x].siz))*alpha > (double(max(tr[lc].siz,tr[rc].siz))) )
        {
            int gf=tmp[i-1],goat=x,w;
            if(tr[gf].son[0]==goat)w=0;
            else w=1;
            rebuild(gf,goat,w);
            break;
        }
    }
}//--------------------ins-------------------

int findrank(int d)
{
    int x=root,ret=1;
    while(x!=0)
    {
        if(d<=tr[x].c)x=tr[x].son[0];
        else ret+=tr[tr[x].son[0]].siz+tr[x].alive, x=tr[x].son[1];
    }
    return ret;
}
void del(int d)
{
    int x=root,k=findrank(d);
    while(x!=0)
    {
        tr[x].siz--;
        int lc=tr[x].son[0],rc=tr[x].son[1];
        if(tr[lc].siz+1==k&&tr[x].alive==1){tr[x].alive=0;break;}
        else if(k<=tr[lc].siz)x=lc;
        else k-=tr[lc].siz+tr[x].alive, x=rc;
    }
    if( (double(tr[root].tot))*alpha > (double(tr[root].siz)) )rebuild(0,root,0);
}//--------------------del--------------------

//------------------simple---------------

int findmath(int k)
{
    int x=root;
    while(x!=0)
    {
        int lc=tr[x].son[0],rc=tr[x].son[1];
        if(tr[lc].siz+1==k&&tr[x].alive==1)return tr[x].c;
        else if(k<=tr[lc].siz)x=lc;
        else k-=tr[lc].siz+tr[x].alive, x=rc;
    }
}

//----------for the problem------------

int main()
{
    freopen("ptszs.in","r",stdin);
    freopen("ptszs.out","w",stdout);
    int n,op,x;
    scanf("%d",&n);
    root=0;
    for(int i=205000;i>=1;i--)sta[++top]=i;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&op,&x);
             if(op==1)ins(x);
        else if(op==2)del(x);
        else if(op==3)printf("%d
",findrank(x));
        else if(op==4)printf("%d
",findmath(x));
        else if(op==5)printf("%d
",findmath(findrank(x)-1));
        else if(op==6)printf("%d
",findmath(findrank(x+1)));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/AKCqhzdy/p/8601446.html