洛谷 P3369 【模板】普通平衡树(Treap/SBT)

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  1. 插入x数
  2. 删除x数(若有多个相同的数,因只删除一个)
  3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
  4. 查询排名为x的数
  5. 求x的前驱(前驱定义为小于x,且最大的数)
  6. 求x的后继(后继定义为大于x,且最小的数)

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例:

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

输出样例:

106465
84185
492737


Splay 解析尚未完成 参见yyb dalao的博客

丑陋的代码送上(yyb大佬的代码比我的漂亮多了):

#ifndef SPLAY_TREE_HPP
#define SPLAY_TREE_HPP
#include<bits/stdc++.h>
using namespace std;
namespace Splay_tree
{
    template<typename T>
    struct splay_node
    {
        T value;
        int size;
        int cnt;
        bool reverse;
        splay_node *father;
        splay_node *son[2];
        splay_node(){}
        splay_node(T v, splay_node *f=NULL)
            :value(v),cnt(1)
        {
            father=f;
            size=0;
            son[0]=son[1]=NULL;
        }
    };

    template<typename T, typename C=less<T> >
    class Splay
    {
        private:
            typedef splay_node<T> node;
            node *root;
            C small_to;
            bool big_to(T x, T y){return small_to(y,x);}
            bool equal_to(T x, T y){return !(small_to(x,y)||big_to(x,y));}

            inline bool son(node *f, node *s)
            {
                return f->son[1]==s;
            }
            inline void rotate(node *t)
            {
                node *f = t->father;
                node *g = f->father;
                bool a = son(f, t), b = !a;
                f->son[a] = t->son[b];
                if (t->son[b] != NULL)
                    t->son[b]->father = f;
                t->son[b] = f;
                f->father = t;
                t->father = g;
                if (g != NULL)
                    g->son[son(g, f)] = t;
                else
                    root = t;
                update(f);
                update(t);
            }

            inline void splay(node *t, node *p)
            {
                while (t->father != p)
                {
                    node *f = t->father;
                    node *g = f->father;
                    if (g == p)
                        rotate(t);
                    else
                    {
                        if (son(g, f) ^ son(f, t)) rotate(t), rotate(t);
                        else rotate(f), rotate(t);
                    }
                }
                update(t);
            }

            inline T k_th(int k, node *f)
            {
                int tmp;
                node *t=root;
                while(1)
                {
                    int tmp=size(t->son[0])+t->cnt;
                    int sze=tmp-t->cnt;
                    if(k<=tmp&&sze<k) break;
                    else if(k<=sze) t=t->son[0];
                    else k-=tmp,t=t->son[1];
                }
                T ans=t->value;
                return ans;
            }

            inline node* insert(T val, node *t)
            {
                int b=big_to(val,t->value);
                if(equal_to(val,t->value))
                {
                    t->cnt++;
                    update(t);
                    return t;
                }
                if(t->son[b]==NULL)
                {
                    t->son[b]=new node(val,t);
                    update(t->son[b]);
                    update(t);
                    return t->son[b];
                }
                else
                {
                    node *ans=insert(val,t->son[b]);
                    update(t);
                    return ans;
                }
            }

        public:
            Splay()
            {
                root=NULL;
            }

            inline void insert(T val)
            {
                if (root == NULL)
                {
                    root = new node(val, NULL);
                    update(root);
                    return;
                }
                else
                {
                    node *t = insert(val,root);
                    splay(t,NULL);
                }
            }

            inline void erase(T val)
            {
                node *t = root;
                while(t)
                {
                    if (equal_to(t->value,val))
                        break;
                    t = t->son[big_to(val,t->value)];
                }
                if (t != NULL)
                {
                    splay(t, NULL);
                    if(t->cnt>1)
                    {
                        t->cnt--;
                        update(t);
                        return;
                    }
                    if (t->son[0] == NULL)
                    {
                        root = t->son[1];
                        if (root != NULL)
                        {
                            root->father = NULL;
                            update(root);
                        }
                    }
                    else
                    {
                        node *p = t->son[0];
                        while (p->son[1] != NULL)
                            p = p->son[1];
                        splay(p, t); root = p;
                        root->father = NULL;
                        p->son[1] = t->son[1];
                        update(p);
                        if (p->son[1] != NULL)
                            p->son[1]->father = p;
                    }
                }
            }

            inline T pre(T val)
            {
                T ans=pre_ptr(val)->value;
                return ans;
            }

            inline T suc(T val)
            {
                node *x = root;
                insert(val);
                node *t=root->son[1];
                if(t==NULL) return T(NULL);
                while(t->son[0]!=NULL) t=t->son[0];
                erase(val);
                T ans=t->value;
                return ans;
            }

            inline T max_value()
            {
                node *t=root;
                while(t->son[1]!=NULL) t=t->son[1];
                return t->value;
            }

            inline T min_value()
            {
                node *t=root;
                while(t->son[0]!=NULL) t=t->son[0];
                return t->value;
            }

            inline T k_th(int k)
            {
                return k_th(k,NULL);
            }

            inline int rank(T val)
            {
                node *t=root;
                while(!equal_to(t->value, val))
                    t=t->son[big_to(val,t->value)];
                splay(t,NULL);
                return size(t->son[0])+1;
            }

            inline void print()
            {
                print(root);
                puts("");
            }

        private:

            inline node* pre_ptr(T val)
            {
                insert(val);
                node *t=root->son[0];
                if(t==NULL) return NULL;
                while(t->son[1]!=NULL) t=t->son[1];
                erase(val);
                return t;
            }

            inline void print(node *t)
            {
                if(t==NULL) return;
                print(t->son[0]);
                printf("%d ",t->value);
                print(t->son[1]);
            }

            inline int size(node *t)
            {
                return t == NULL ? 0 : t->size;
            }

            inline void update(node *t)
            {
                t->size = t->cnt;
                t->size += size(t->son[0]);
                t->size += size(t->son[1]);
            }
    };
}
#endif

int main()
{
    using namespace Splay_tree;
    int n;
    Splay<int> tree;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int ops;
        int x;
        scanf("%d%d",&ops,&x);
        switch(ops)
        {
            case 1:
                tree.insert(x);
                break;
            case 2:
                tree.erase(x);
                break;
            case 3:
            {
                int t=tree.rank(x);
                printf("%d\n",t);
                break;
            }
            case 4:
            {
                int y=tree.k_th(x);
                printf("%d\n",y);
                break;
            }
            case 5:
                printf("%d\n",tree.pre(x));
                break;
            case 6:
                int t=tree.suc(x);
                printf("%d\n",t);
                break;
        }
    }
}

时间: 2024-10-19 04:23:32

洛谷 P3369 【模板】普通平衡树(Treap/SBT)的相关文章

luoguP3369[模板]普通平衡树(Treap/SBT) 题解

链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #include<cstring> #include<iomanip> #include<algorithm> #include<ctime> #include<queue> #incl

【洛谷P3369】普通平衡树(splay)

emmmmm直接丢代码了 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<set> #include<map> #include<queue> #include<algorithm> #include<vector> #include<cstdlib> #include<

AC日记——【模板】普通平衡树(Treap/SBT) 洛谷 P3369

[模板]普通平衡树(Treap/SBT) 思路: 劳资敲了一个多星期: 劳资终于a了: 劳资一直不a是因为一个小错误: 劳资最后看的模板: 劳资现在很愤怒: 劳资不想谈思路!!! 来,上代码: #include <cstdio> using namespace std; #define maxn 1000005 struct SplayTreeNodeType { int w,key,opi,size,ch[2]; }; struct SplayTreeNodeType tree[maxn];

洛谷3380 二逼平衡树(树套树)

题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数值 查询k在区间内的前驱(前驱定义为严格小于x,且最大的数,若不存在输出-2147483647) 查询k在区间内的后继(后继定义为严格大于x,且最小的数,若不存在输出2147483647) 注意上面两条要求和tyvj或者bzoj不一样,请注意 输入输出格式 输入格式: 第一行两个数 n,m 表示长度为n的有序序列和m个操作 第二行有n个数,

【C++】最近公共祖先LCA(Tarjan离线算法)&amp;&amp; 洛谷P3379LCA模板

1.前言 首先我们介绍的算法是LCA问题中的离线算法-Tarjan算法,该算法采用DFS+并查集,再看此算法之前首先你得知道并查集(尽管我相信你如果知道这个的话肯定是知道并查集的),Tarjan算法的优点在于相对稳定,时间复杂度也比较居中,也很容易理解(个人认为). 2.思想 下面详细介绍一下Tarjan算法的思想: 1.任选一个点为根节点,从根节点开始. 2.遍历该点u所有子节点v,并标记这些子节点v已被访问过. 3.若是v还有子节点,返回2,否则下一步. 4.合并v到u上. 5.寻找与当前点

AC自动机(附洛谷P3769模板题)

首先,介绍一下AC自动机(Aho-Corasick automaton),是一种在一个文本串中寻找每一个已给出的模式串的高效算法. 在学习AC自动机之前,你需要先学习Trie树和KMP算法,因为AC自动机正式利用并结合了两者的思想. 说到实际的不同,其实AC自动机只是在Trie树上引入了一个类似KMP中next数组的东西叫做Fail指针. 对于每一个节点,Fail指针指向该节点所代表的字符串中,次长的.在Trie树中存在的后缀(因为最长的在Trie树种存在的后缀就是其本身)所代表的节点. 举例:

洛谷P3375 [模板]KMP字符串匹配

To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整

洛谷.3803.[模板]多项式乘法(FFT)

题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. #include <cmath> #include <cctype> #include <cstdio> #include <algorithm> #define gc() getchar() const int N=1e6+5; const double PI=acos(-1); int n,m; struct Complex { double

洛谷.1919.[模板]A乘B Problem升级版(FFT)

题目链接:洛谷.BZOJ2179 //将乘数拆成 a0*10^n + a1*10^(n-1) + ... + a_n-1的形式 //可以发现多项式乘法就模拟了竖式乘法 所以用FFT即可 注意处理进位 //n位*n位最多就只有2n位了 //论putchar的速度..还是快的 #include <cmath> #include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar

洛谷 P3369 BZOJ 3224 【模板】普通平衡树(Treap/SBT)

题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除x数(若有多个相同的数,因只删除一个) 查询x数的排名(若有多个相同的数,因输出最小的排名) 查询排名为x的数 求x的前驱(前驱定义为小于x,且最大的数) 求x的后继(后继定义为大于x,且最小的数) 输入输出格式 输入格式: 第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6) 输出格式: 对于操作3,4,5,6每行输出一个数,表示对应答案 输