• 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;
    }
  • 相关阅读:
    @ControllerAdvice 全局异常处理
    SpringBoot 单文件和多文件上传
    Springboot application 本地HTTPS配置
    不使用spring-boot-starter-parent进行依赖的版本管理
    构造函数和函数式接口
    函数式接口和Lambda表达式
    使用FunctionalInterface提供工厂方法
    Future 和 CompletableFuture 异步任务 in Java
    单例
    使用私有仓库(Docker Registry 2.0)管理镜像
  • 原文地址:https://www.cnblogs.com/Miracevin/p/9898179.html
Copyright © 2020-2023  润新知