bzoj3224 普通平衡树

Description

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

Input

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

Output

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

treap维护每个节点的数值和子树大小。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#define clr(a) memset(a,0,sizeof(a))
#define N 100001
int ch[N][2];
int sz[N],a[N];
int v[N];
int p=1,V;
inline void preins(int x){
    v[p]=V=x;
    sz[p]=1;
    a[p]=rand();
}
inline void upd(int x){
    if(x)sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
}
struct bst{
    int root;
    bst(){
        root=0;
    }
    void insert(){
        if(root)insert(root);
        else root=p++;
    }
    void insert(int&x){
        bool d=V>v[x];
        int&c=ch[x][d];
        if(c)insert(c);
        else c=p++;
        if(a[ch[x][d]]>a[x])rot(x,d);
        upd(x);
    }void rot(int&w,int c){
        int u=ch[w][c];
        ch[w][c]=ch[u][c^1];
        ch[u][c^1]=w;
        upd(w);
        w=u;
        upd(u);
    }
    int lss(int x){
        int w=root,ans=0;
        while(w){
            if(v[w]<x)ans+=sz[ch[w][0]]+1;
            w=ch[w][v[w]<x];
        }
        return ans;
    }
    void del(int&w,int V){
        if(!w)return;
        if(v[w]==V)del(w);
        else del(ch[w][v[w]<V],V);
        upd(w);
    }
    void del(int&w){
        if(ch[w][0]|ch[w][1]){
            bool d=a[ch[w][0]]<a[ch[w][1]];
            int u=ch[w][d];
            rot(w,d);
            del(ch[w][d^1]);
            upd(u);
        }else w=0;
    }
    int prv(int x){
        int w=root,a=-1;
        while(w){
            if(x>v[w])a=v[w];
            w=ch[w][x>v[w]];
        }
        return a;
    }
    int nxt(int x){
        int w=root,a=-1;
        while(w){
            if(x<v[w])a=v[w];
            w=ch[w][x>=v[w]];
        }
        return a;
    }
    int rnkx(int x){
        int w=root,a=sz[ch[w][0]]+1;
        while(a^x){
            if(x<a)w=ch[w][0],a-=sz[ch[w][1]]+1;
            else w=ch[w][1],a+=sz[ch[w][0]]+1;
        }
        return v[w];
    }
};
bst b;
int n,p1,p2;
int main(){
    freopen("in.txt","r",stdin);
    freopen("o.txt","w",stdout);
    clr(ch);clr(sz);clr(a);clr(v);
    a[0]=-1;
    scanf("%d",&n);
    while(n--){
        scanf("%d%d",&p1,&p2);
        switch(p1){
            case 1:preins(p2);b.insert();break;
            case 2:b.del(b.root,p2);break;
            case 3:printf("%d\n",b.lss(p2)+1);break;
            case 4:printf("%d\n",b.rnkx(p2));break;
            case 5:printf("%d\n",b.prv(p2));break;
            case 6:printf("%d\n",b.nxt(p2));break;
        }
    }
    return 0;
}
时间: 2024-10-13 06:08:23

bzoj3224 普通平衡树的相关文章

[BZOJ3224]普通平衡树(旋转treap)

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 20328  Solved: 8979[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为

bzoj3224 普通平衡树(splay 模板)

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 11427  Solved: 4878[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为

[TYVJ1728/BZOJ3224]普通平衡树-替罪羊树

Problem 普通平衡树 Solution 本题是裸的二叉平衡树.有很多种方法可以实现.这里打的是替罪羊树模板. 此题极其恶心. 前驱后继模块需要利用到rank模块来换一种思路求. 很多细节的地方容易炸.我拿数据调了很久才A. (delt()删除模块其实是不需要重建的,不影响时间复杂度) 替罪羊树具体详见此篇知乎:替罪羊树 AC Code 1 #include "iostream" 2 #include "cstdio" 3 #define alpha 0.7 4

[您有新的未分配科技点]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)

今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和treap一样简单易懂,同时还支持可持久化. 无旋treap的节点定义和treap一样,都要同时满足树性质和堆性质,我们还是用rand()来实现平衡 而无旋treap与treap不同的地方,也是其核心,就是它不旋转用两个新的核心函数:merge函数(合并两棵子树)和split函数(分裂出某棵树的前k个节点,并且作为一棵树返回) 首先看merge函数,它是一个递归实现的过程,先看代码: 1 Treap *merge(

Bzoj3224普通平衡树

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

[bzoj3224]普通平衡树[Treap]

Treap 的各种操作,模板题,要再写几遍 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cmath> 7 #include <ctime> 8 9 using namespace std; 10 11 class Treap 12

bzoj3224 普通平衡树 splay模板

题目传送门 题目大意:完成一颗splay树. 思路:模板题,学着还是很有意思的. 学习splay树:蒟蒻yyb 该题模板:汪立超 #include<bits/stdc++.h> #define CLR(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; int root,N=0,n,p,q; int fa[100001],c[100001][2],size[100001],sp[100001]; void

【转】 史上最详尽的平衡树(splay)讲解与模板(非指针版spaly)

ORZ原创Clove学姐: 变量声明:f[i]表示i的父结点,ch[i][0]表示i的左儿子,ch[i][1]表示i的右儿子,key[i]表示i的关键字(即结点i代表的那个数字),cnt[i]表示i结点的关键字出现的次数(相当于权值),size[i]表示包括i的这个子树的大小:sz为整棵树的大小,root为整棵树的根. 再介绍几个基本操作: [clear操作]:将当前点的各项值都清0(用于删除之后) inline void clear(int x){ ch[x][0]=ch[x][1]=f[x]

平衡树讲解(旋转treap,非旋转treap,splay)

在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用的:treap和splay(其中treap包括旋转treap和非旋转treap). 一.treap treap这个词是由tree和heap组合而成,意思是树上的的堆(其实就是字面意思啦qwq).treap可以说是由二叉搜索树(BST)进化而来,二叉搜索树每个点满足它左子树中所有点权值都比它小,它右子