zoukankan      html  css  js  c++  java
  • HihoCoder1337 动态第k大(treap)

    描述

    小Ho:小Hi,之前你不是讲过Splay和Treap么,那么还有没有更简单的平衡树呢?

    小Hi:但是Splay和Treap不是已经很简单了么?

    小Ho:是这样没错啦,但是Splay和Treap和原来的二叉搜索树相比都有很大的改动,我有点记不住。

    小Hi:这样啊,那我不妨再给你讲解一个新的平衡树算法好了。和二叉搜索树相比,它只需要修改insert函数,就可以做到高度的平衡。

    小Ho:好,我就喜欢这样的!

    输入

    第1行:1个正整数n,表示操作数量,10≤n≤100,000

    第2..n+1行:每行1个字母c和1个整数k:

    若c为'I',表示插入一个数字k到树中,-1,000,000,000≤k≤1,000,000,000

    若c为'Q',表示询问树中第k小数字,保证1≤k≤树的节点数量

    输出

    若干行:每行1个整数,表示针对询问的回答,保证一定有合法的解

    样例输入

    5
    I 3
    I 2
    Q 1
    I 5
    Q 2

    样例输出

    2
    3

    先结合Treap和这两天写的结构体试一试。

    其中

    1,rotate函数没差。

    2,update在儿子有变化后都要更新。

    3,insert有‘&’符号,不需要特殊处理root=0的情况

    4,查询kth时注意边界即可推进。

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    using namespace std;
    const int maxn=100010;
    struct treapdata
    {
          int ch[2],size,cnt,val,rnd;
          treapdata(){
                ch[0]=ch[1]=0;
                size=cnt=val=rnd=0;
          }
    };
    struct Treap
    {
        int root,cnt;
        Treap()
        {
            root=cnt=0;
        }
        treapdata S[maxn];
        void update(int now)
        {
            S[now].size=S[now].cnt+S[S[now].ch[0]].size+S[S[now].ch[1]].size;
        }
        void rotate(int &x,int t)
        {
            int y=S[x].ch[t];
            S[x].ch[t]=S[y].ch[1-t];
            S[y].ch[1-t]=x;
            update(x);
            update(y);
            x=y;//!莫忘
        }
        void insert(int &x,int k)
        {
            if(x){
                if(S[x].val==k) S[x].cnt++;
                else{
                    int t=S[x].val<k;
                    insert(S[x].ch[t],k);
                    if(S[S[x].ch[t]].rnd<S[x].rnd) rotate(x,t);
                }
            }
            else{
                x=++cnt;
                S[x].val=k;
                S[x].cnt=1;
                S[x].rnd=rand();
                S[x].ch[0]=S[x].ch[1]=0;
            }
            update(x);
        }
        int querykth(int now,int k)//第k小
        {
            if(k<=S[S[now].ch[0]].size) return querykth(S[now].ch[0],k);
            k=k-S[S[now].ch[0]].size-S[now].cnt;
            if(k<=0) return S[now].val;
            return querykth(S[now].ch[1],k);
        }
    };
    Treap Tp;
    int main()
    {
        int k,n;
        char opt[2];
        scanf("%d",&n);
        while(n--){
            scanf("%s",opt);
            scanf("%d",&k);
            if(opt[0]=='I') Tp.insert(Tp.root,k);
            else printf("%d
    ",Tp.querykth(Tp.root,k));
        }
        return 0;
    }
  • 相关阅读:
    20181123(编码问题)
    20181122笔记(列表、元组、字典和集合的数据类型及内置方法)
    20181121笔记(for,数字类型和字符串类型的内置方法)
    20181120笔记
    Python的第3堂课
    错误集合(想起来就更新)
    Python的第二堂课(2)
    Python的第二堂课(1)
    boost::bind实践2——来自《Beyond the C++ Standard Library ( An Introduction to Boost )》
    boost::bind实践
  • 原文地址:https://www.cnblogs.com/hua-dong/p/7905606.html
Copyright © 2011-2022 走看看