NOIP2017 列队——平衡树

平衡树蒟蒻,敲了半天。

其实思路很简单,就是把许多个人合并成一个区间。必要的时候再拆开。(是不是和这个题的动态开点线段树有异曲同工之妙?)

每次操作最多多出来6个点。

理论上时间复杂度是nlogn,空间复杂度实际远远小于上界,其实4*n即可。

出错点:

1.pushup把哨兵sz变成了1:pushup要特判x!=0(比较保险)

2.fa和son的边一定要成对一起添加!!t[t[y].ch[0]=t[x].ch[0]].fa=y 压行的话不容易漏。

3.对于一列的情况,可能删除之后整个树空了。但是如果直接找的话,因为哨兵0有奇奇怪怪的左右儿子和father,所以,一路上会把0的sz变成1,并且访问到奇奇怪怪的点23333

那就特判如果没有根的话,那就直接建立即可。

代码:

#include<bits/stdc++.h>
#define reg register int
#define il inline
using namespace std;
typedef long long ll;
const int N=300000+5;
struct node{
    int ch[2];
    int sz;
    int L,R;
    int fa;
    ll val;
}t[N*6];
int tot;
void rd(int &x){
    char ch;x=0;
    while(!isdigit(ch=getchar()));
    for(x=ch^'0';isdigit(ch=getchar());x=x*10+(ch^'0'));
}
int rt[N];
int now;
int n,m,q;
void pushup(int x){
    if(x)
    t[x].sz=t[t[x].ch[0]].sz+t[t[x].ch[1]].sz+t[x].R-t[x].L+1;
}
void rotate(int x){
    int y=t[x].fa,d=(t[y].ch[1]==x);
    t[t[y].ch[d]=t[x].ch[!d]].fa=y;
    t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[1]==y]=x;
    t[t[x].ch[!d]=y].fa=x;
    pushup(y);
}
void splay(int x,int f){
    while(t[x].fa!=f){
        int y=t[x].fa,z=t[y].fa;
        if(z!=f){
            rotate((t[y].ch[0]==x)==(t[z].ch[0]==y)?y:x);
        }
        rotate(x);
    }
    pushup(x);
    if(f==0) rt[now]=x;
}
ll get(int pos){
    if(now==n+1){
        return (ll)pos*m;
    }
    return (ll)(now-1)*m+pos;
}
void ins(int x,ll c){
    if(x==0){
        ++tot;
        t[tot].fa=0;
        t[tot].val=c;
        t[tot].L=t[tot].R=0;
        pushup(tot);
        rt[now]=tot;
    }
    else{
        while(t[x].ch[1]) t[x].sz++,x=t[x].ch[1];
    
        ++tot;
        t[x].ch[1]=tot;
        t[tot].fa=x;
        t[tot].L=t[tot].R=0;t[tot].val=c;
        t[tot].sz=1;
        pushup(x);    
        splay(tot,0);
        int tmp=rt[now];
    }
}
ll query(int x,int k){//and dele
    int d=k-t[t[x].ch[0]].sz;
    if(d<=0) return query(t[x].ch[0],k);
    else if(t[x].R-t[x].L+1<d) return query(t[x].ch[1],d-(t[x].R-t[x].L+1));
    else{//find position
        ll ret=0;
        if(t[x].R>t[x].L){
            if(d>1){
                ++tot;
                t[tot].L=t[x].L;t[tot].R=t[x].L+d-2;
                t[t[tot].ch[0]=t[x].ch[0]].fa=tot;
                t[t[x].ch[0]=tot].fa=x;
                pushup(tot);
            }
            if(d<t[x].R-t[x].L+1){
                ++tot;
                t[tot].L=t[x].L+d;t[tot].R=t[x].R;
                t[t[tot].ch[1]=t[x].ch[1]].fa=tot;
                t[t[x].ch[1]=tot].fa=x;
                pushup(tot);
            }
            t[x].val=get(t[x].L+d-1);
            t[x].L=t[x].R=0;
        }else if(t[x].R){
            t[x].val=get(t[x].R);
            t[x].L=t[x].R=0;
        }
        pushup(x);
        
        ret=t[x].val;
        
        splay(x,0);
        int son=t[x].ch[1];
        if(!son){
            t[rt[now]=t[x].ch[0]].fa=0;
            pushup(rt[now]);
        }
        else{
            while(t[son].ch[0]) son=t[son].ch[0];
            splay(son,rt[now]);
            
            t[t[son].ch[0]=t[x].ch[0]].fa=son;
            t[son].fa=0;
            pushup(son);
            rt[now]=son;
        }
        return ret;
    }
}
int main(){
    rd(n);rd(m);rd(q);
    int x,y;
    for(reg i=1;i<=n;++i){
        rt[i]=++tot;
        t[tot].L=1,t[tot].R=m-1;
        t[tot].sz=m-1;
        t[tot].fa=0;
    }
    rt[n+1]=++tot;
    t[tot].L=1,t[tot].R=n;
    t[tot].sz=n;
    while(q--){
        rd(x);rd(y);
        ll id=0;
        if(y==m) now=n+1,id=query(rt[now],x);
        else now=x,id=query(rt[now],y);
        printf("%lld
",id);
        now=n+1;
        ins(rt[now],id);
        if(y!=m){
            now=n+1;
            id=query(rt[now],x);
            now=x;
            ins(rt[now],id);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Miracevin/p/9898179.html