BZOJ 3224 普通平衡树(treap模板题)

3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 14301  Solved: 6208
[Submit][Status][Discuss]

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每行输出一个数,表示对应答案

Sample Input

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

Sample Output

106465
84185
492737

HINT

1.n的数据范围:n<=100000

2.每个数的数据范围:[-2e9,2e9]

题目链接:BZOJ 3224

刚学了一下treap,照着模版和自己的理解,果然数据结构很多都是码农题……可以发现treap就是一颗在插入和删除操作的时候会进行一些平衡调整的BST,就当是treap练手题了。

这题用离线下的离散化+线段树应该也是可以AC的,姿势有很多种就对了……

代码:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 100010;
struct Node
{
    int ls, rs, v, cnt, sz;
    int rnd;
};
Node T[N];
int tot, root;

void init()
{
    tot = 0;
}
void pushup(int k)
{
    T[k].sz = T[T[k].ls].sz + T[T[k].rs].sz + T[k].cnt;
}
void lturn(int &k)
{
    int rs = T[k].rs;
    T[k].rs = T[rs].ls;
    T[rs].ls = k;
    T[rs].sz = T[k].sz;
    pushup(k);
    k = rs;
}
void rturn(int &k)
{
    int ls = T[k].ls;
    T[k].ls = T[ls].rs;
    T[ls].rs = k;
    T[ls].sz = T[k].sz;
    pushup(k);
    k = ls;
}
void ins(int &k, int v)
{
    if (!k)
    {
        k = ++tot;
        T[k].ls = T[k].rs = 0;
        T[k].v = v;
        T[k].cnt = T[k].sz = 1;
        T[k].rnd = rand();
    }
    else
    {
        ++T[k].sz;
        if (v == T[k].v)
            ++T[k].cnt;
        else if (v < T[k].v)
        {
            ins(T[k].ls, v);
            if (T[T[k].ls].rnd < T[k].rnd)
                rturn(k);
        }
        else
        {
            ins(T[k].rs, v);
            if (T[T[k].rs].rnd < T[k].rnd)
                lturn(k);
        }
    }
}
void del(int &k, int v)
{
    if (!k)
        return ;
    if (v == T[k].v)
    {
        if (T[k].cnt > 1)
        {
            --T[k].cnt;
            --T[k].sz;
            return ;
        }
        if (T[k].ls * T[k].rs == 0)
            k = T[k].ls + T[k].rs;
        else if (T[T[k].ls].rnd < T[T[k].rs].rnd)
        {
            rturn(k);
            del(k, v);
        }
        else
        {
            lturn(k);
            del(k, v);
        }
    }
    else if (v < T[k].v)
    {
        --T[k].sz;
        del(T[k].ls, v);
    }
    else
    {
        --T[k].sz;
        del(T[k].rs, v);
    }
}
int query_rank(int k, int x)
{
    if (!k)
        return 0;
    else
    {
        if (T[k].v == x)
            return T[T[k].ls].sz + 1;
        else if (x < T[k].v)
            return query_rank(T[k].ls, x);
        else
            return T[T[k].ls].sz + T[k].cnt + query_rank(T[k].rs, x);
    }
}
int query_kth(int k, int pos)
{
    if (!k)
        return 0;
    if (pos <= T[T[k].ls].sz)
        return query_kth(T[k].ls, pos);
    else if (pos > T[T[k].ls].sz + T[k].cnt)
        return query_kth(T[k].rs, pos - T[T[k].ls].sz - T[k].cnt);
    else
        return T[k].v;
}
void query_pre(int k, int v, int &ans)
{
    if (!k)
        return;
    if (T[k].v < v)
    {
        ans = k;
        query_pre(T[k].rs, v, ans);
    }
    else
        query_pre(T[k].ls, v, ans);
}
void query_post(int k, int v, int &ans)
{
    if (!k)
        return ;
    if (T[k].v > v)
    {
        ans = k;
        query_post(T[k].ls, v, ans);
    }
    else
        return query_post(T[k].rs, v, ans);
}
int main(void)
{
    srand(987654321);
    int n, x, ops, idx;
    while (~scanf("%d", &n))
    {
        init();
        while (n--)
        {
            scanf("%d%d", &ops, &x);
            switch(ops)
            {
            case 1:
                ins(root, x);
                break;
            case 2:
                del(root, x);
                break;
            case 3:
                printf("%d\n", query_rank(root, x));
                break;
            case 4:
                printf("%d\n", query_kth(root, x));
                break;
            case 5:
                query_pre(root, x, idx);
                printf("%d\n", T[idx].v);
                break;
            case 6:
                query_post(root, x, idx);
                printf("%d\n", T[idx].v);
                break;
            }
        }
    }
    return 0;
}
时间: 2024-11-14 00:16:41

BZOJ 3224 普通平衡树(treap模板题)的相关文章

BZOJ1208: [HNOI2004]宠物收养所 平衡树 Treap 模板题

Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被 主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希 望领养的宠物的特点值a(a是一个正整数,a<2^31),而他也给每个处在收养所的宠物一个特点值.这样他就能够很方便的处理整个领养宠物的过程 了,宠物收养所总是会有两种情况发生:被遗弃的宠物过多或者是想要收养宠物的人太多,而宠物太少. 1. 被遗弃的宠物过多时,假若到来一个

BZOJ 1036 树链剖分模板题

BZOJ 1036 题意:一棵树,每个点有权值,三种操作:修改一个点的值:询问一条链上最大值:询问一条链上权值和. tags:模板题 // bzoj 1036 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define FF(i,a,b) for (int i=a;i<=b;i++) #define F(i,b,a)

POJ1442-查询第K大-Treap模板题

模板题,以后要学splay,大概看一下treap就好了. 1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 5 using namespace std; 6 7 const int maxn = 3e5+10; 8 int num[maxn],st[maxn]; 9 10 struct Treap{ 11 int size; 12 int key,fix; 13 Treap *ch[2];

在洛谷3369 Treap模板题 中发现的Splay详解

本题的Splay写法(无指针Splay超详细) 前言 首先来讲...终于调出来了55555...调了整整3天..... 看到大部分大佬都是用指针来实现的Splay.小的只是按照Splay的核心思想和原理来进行的.可能会有不妥之处,还请大佬们指出,谢谢! 那么这个题解存在的意义就是让不会敲Splay的人额...会敲Splay啦... 基本思想 数据结构 对于Splay,我定义了一个class类(当成struct就行啦...个人习惯不同啦),定义名称为“Splay”. 之后在类中,我定义了Splay

[代码] bzoj 3224 普通平衡树(无旋treap)

- 传送门 - http://www.lydsy.com/JudgeOnline/problem.php?id=3224 3224: Tyvj 1728 普通平衡树 Time Limit:?10 Sec??Memory Limit:?128 MB Submit:?17311??Solved:?7553 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 1. 插入x数 2. 删除x数(若有多个相同的数,因只删除一个) 3. 查询x数的排名(若有多

[BZOJ 3224] 普通平衡树 非旋Treap

题意 维护一个多重集合 $S$ , 支持: ① 插入一个数 $w$ . ② 删除一个数 $w$ . ③ 查询 $w$ 在集合中的排名. ④ 查询集合中排名第 $r$ 的数. ⑤ 求集合中 $w$ 的前驱. ⑥ 求集合中 $w$ 的后继. $N \le 100000$ . 小结 要总结一些常见的写法和想法, 减小实现时的复杂度. 实现 #include <cstdio> #include <cstring> #include <cstdlib> #include <

BZOJ 3224 普通平衡树

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每行输

BZOJ 3224 普通平衡树 平衡树的两种姿势:SBT,splay

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

Bzoj 1251: 序列终结者 (Splay 模板题)

题面(太裸太裸,不看也罢) 就是维护一个区间加,区间翻转和区间最大值. 贴一个风格以后可以一直用 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define N 100000 6 #define XX getchar() 7 using namespace std; 8 int ch[N][2],fa[N],rev[N],ad[N],b