zoukankan      html  css  js  c++  java
  • TYVJ P1728 普通平衡树

    P1728 普通平衡树

    时间: 1000ms / 空间: 131072KiB / Java类名: Main

    背景

    此为平衡树系列第一道:普通平衡树

    描述

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
    1. 插入x数
    2. 删除x数(若有多个相同的数,因只删除一个)
    3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
    4. 查询排名为x的数
    5. 求x的前驱(前驱定义为小于x,且最大的数)
    6. 求x的后继(后继定义为大于x,且最小的数)

    输入格式

    第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

    输出格式

    对于操作3,4,5,6每行输出一个数,表示对应答案

    测试样例1

    输入

    1 10 
    1 20 
    1 30 
    3 20 
    4 2 
    2 10 
    5 25 
    6 -1

    输出


    20 
    20 
    20
     
    splay裸体,无聊随便打一打,多练练手吧。
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define mod
    #define M 1000010
    using namespace std;
    LL read(){
        LL nm=0,oe=1;char cw=getchar();
        while(!isdigit(cw)) oe=cw=='-'?-oe:oe,cw=getchar();
        while(isdigit(cw)) nm=nm*10+(cw-'0'),cw=getchar();
        return nm*oe;
    }
    LL n,m,l[M],r[M],sz[M],tp[M],p[M],num[M],cnt,T,ace,typ;
    inline void pushup(LL x){sz[x]=sz[l[x]]+sz[r[x]]+num[x];}
    void rotate(LL x){
        if(x==ace) return;
        LL top=tp[x];sz[x]=sz[top];
        if(l[top]==x) sz[top]=sz[r[top]]+sz[r[x]]+num[top];
        else sz[top]=sz[l[top]]+sz[l[x]]+num[top];
        if(top==ace){ace=x,tp[top]=ace;}
        else{
            tp[x]=tp[top];
            if(l[tp[top]]==top) l[tp[top]]=x,tp[top]=x;
            else r[tp[top]]=x,tp[top]=x;
        }
        if(l[top]==x) l[top]=r[x],tp[r[x]]=top,r[x]=top;
        else r[top]=l[x],tp[l[x]]=top,l[x]=top;
    }
    void splay(LL x){
        while(ace!=x){
            LL top=tp[x];
            if(top==ace) rotate(x);
            else if(l[l[tp[top]]]==x||r[r[tp[top]]]==x) rotate(top);
            else rotate(x);
        }
    }
    void insert(LL x){
        if(ace==0){ace=++cnt,p[ace]=x,sz[ace]=num[ace]=1;return;}
        LL k=ace,last=0,sta=0,CNT=0;
        while(true){
            if(k==0){
                p[++cnt]=x,tp[cnt]=last,sz[cnt]=num[cnt]=1;
                if(sta==1) r[last]=cnt;
                else l[last]=cnt;
                break;
            }
            last=k;
            if(p[k]<x) k=r[k],sta=1;
            else if(p[k]>x) k=l[k],sta=2;
            else{num[k]++;break;}
        }
        while(true){
            sz[last]++,CNT++;
            if(last==ace) break;
            last=tp[last];
        }
        splay(cnt);
    }
    LL find(LL x){
        LL k=ace,CT=0;
          while(p[k]!=x&&k>0){
            if(p[k]>x) k=l[k];
            else k=r[k];
            CT++;
        }
        if(CT>=50&&k>0) splay(k);
        return k;
    }
    LL gt(LL x,LL tpe){
        LL k=find(x),rt1=-100000012,rt2=100000012;
        if(k==0){
            for(LL t=ace;t>0;){
                if(p[t]>x) rt2=min(rt2,p[t]),t=l[t];
                else rt1=max(rt1,p[t]),t=r[t];
            }
            return tpe==0?rt1:rt2;
        }
        splay(k);
        for(LL t=l[k];t!=0;t=r[t]) rt1=max(rt1,p[t]);
        for(LL t=r[k];t!=0;t=l[t]) rt2=min(rt2,p[t]);
        return tpe==0?rt1:rt2;
    }
    LL ord(LL x){
        LL k=find(x);
        splay(k);
        return sz[l[k]]+1;
    }
    LL getnum(LL x){
        LL k=ace,od=x;
        while(sz[l[k]]+1>od||sz[l[k]]+num[k]<od){
            if(sz[l[k]]+1>od) k=l[k];
            else od-=sz[k]-sz[r[k]],k=r[k];
        }
        return k;
    }
    void del(LL x){
        LL pos=find(x),last=0;
        if(num[pos]>1){
           num[pos]--,last=pos;
            while(true){
                sz[last]--;
                if(last==ace) break;
                last=tp[last];
            }
            return;
        }
        splay(pos),sz[pos]--;
        if(l[pos]==0&&r[pos]==0){ace=0;return;}
        else if(l[pos]==0) ace=r[pos];
        else if(r[pos]==0) ace=l[pos];
        else{
            LL ss=l[pos];
            if(r[ss]==0){
                p[pos]=p[ss],num[pos]=num[ss];
                tp[l[ss]]=tp[ss],l[tp[ss]]=l[ss];
                return;
            }
            while(r[ss]>0) ss=r[ss];
            p[pos]=p[ss],num[pos]=num[ss];
            tp[l[ss]]=tp[ss],r[tp[ss]]=l[ss];
            for(LL i=l[ss];i!=ace;i=tp[i]) pushup(tp[i]);
        }
    }
    int main(){
        T=read();
        while(T--){
            typ=read(),m=read(),num[0]=find(m);
            if(typ==1) insert(m);
            else if(typ==2) del(m);
            else if(typ==3) printf("%lld
    ",ord(m));
            else if(typ==4) printf("%lld
    ",p[getnum(m)]);
            else printf("%lld
    ",gt(m,typ-5));
        }
        return 0;
    }
     
  • 相关阅读:
    学习日志---4.5.6
    学习日志---3
    学习日志---2
    学习日志---1
    阅读《大型网站技术架构:核心原理与案例分析》第五、六、七章
    淘宝网的质量属性的六个常见属性场景
    虚继承 private virtual class
    C++ 类中什么时候需要一个operator<
    C++ 中关于 输出的重定向
    C++ 元编程 学习二
  • 原文地址:https://www.cnblogs.com/OYJason/p/7930505.html
Copyright © 2011-2022 走看看