luogu3369【模板】普通平衡树(Treap/SBT)

题目链接
此题要求实现6种操作

  • 插入x
  • 删除x
  • 查询x数的排名
  • 查询排名为x的数
  • 求x的前驱
  • 求x的后继

既然题目已经明确指出了可以使用treap,那就写一个指针版不维护父节点的treap。

#include<bits/stdc++.h>
#define N 100001 
using namespace std;

struct Treap
{
    int value, rank, size, re;
    Treap * l, * r;
}p[N], * root = NULL;

int len = 0;
int n, ans;

inline int read()
{
    int f = 0, fu = 1;
    char c = getchar();
    while(c < '0' || c > '9')
    {
        if(c == '-') fu = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9')
    {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}
inline void update(Treap * u)
{
    u -> size = u -> re;
    if(u -> l != NULL) u -> size += u -> l -> size;
    if(u -> r != NULL) u -> size += u -> r -> size; 
}
inline void tl(Treap *& u)
{
    Treap * tmp = u -> r;
    u -> r = tmp -> l;
    tmp -> l = u; 
    tmp -> size = u -> size;
    update(u);
    u = tmp;
}
inline void tr(Treap *& u)
{
    Treap * tmp = u -> l;
    u -> l = tmp -> r;
    tmp -> r = u;
    tmp -> size = u -> size;
    update(u);
    u = tmp; 
}
inline void in_Treap(Treap *& u, int x)
{
    if(u == NULL)
    {
        u = &p[++len];
        u -> value = x;
        u -> rank = rand();
        u -> size = 1;
        u -> re = 1;
        u -> l = NULL;
        u -> r = NULL; 
        return;
    }
    u -> size++;
    if(u -> value == x)
    {
        u -> re++;
        return;
    }
    if(u -> value > x)
    {
        in_Treap(u -> l, x);
        if(u -> l -> rank < u -> rank) tr(u);
    }
    else
    {
        in_Treap(u -> r, x);
        if(u -> r -> rank < u -> rank) tl(u);
    }
}
inline void delete_Treap(Treap *& u, int x)
{
    if(u == NULL) return;
    if(u -> value == x)
    {
        if(u -> re >= 2)
        {
            u -> re--;
            u -> size--;
            return;
        }
        if(u -> l == NULL) u = u -> r;
        else if(u -> r == NULL) u = u -> l;
        else
        {
            if(u -> l -> rank < u -> r -> rank)
            {
                tr(u);
                delete_Treap(u, x);
            }
            else
            {
                tl(u);
                delete_Treap(u, x);
            }
        }
    }
    else
    {
        if(x < u -> value)
        {
            u -> size--;
            delete_Treap(u -> l, x);
        }
        else
        {
            u -> size--;
            delete_Treap(u -> r, x);
        }
    }
}
inline int find1(Treap * u, int x)
{
    if(u == NULL) return 0;
    if(u -> value == x) 
    {
        if(u -> l != NULL) return u -> l -> size + 1;
        return 1;
    }
    if(u -> value > x) return find1(u -> l, x);
    if(u -> value < x)
    {
        if(u -> l != NULL) return u -> l -> size + u -> re + find1(u -> r, x);
        return find1(u -> r, x) + u -> re;
    }
}
inline int find2(Treap * u, int x)
{
    if(u == NULL) return 0;
    if(u -> l == NULL)
    {
        if(x > u -> re) return find2(u -> r, x - u -> re);
        return u -> value;
    }
    if(x <= u -> l -> size) return find2(u -> l, x);
    if(x > u -> l -> size + u -> re) return find2(u -> r, x - u -> l -> size - u -> re);
    return u -> value;  
} 
inline void find3(Treap * u, int x)
{
    if(u == NULL) return;
    if(u -> value < x)
    {
        ans = u -> value;
        find3(u -> r, x);
    }
    else find3(u -> l, x);
}
inline void find4(Treap * u, int x)
{
    if(u == NULL) return;
    if(u -> value > x)
    {
        ans = u -> value;
        find4(u -> l, x);
    }
    else find4(u -> r, x);
}

int main()
{
    srand(998244353);
    n = read();
    for(int i = 1; i <= n; i++)
    {
        int a = read(), b = read();
        if(a == 1) in_Treap(root, b);
        if(a == 2) delete_Treap(root, b);
        if(a == 3) printf("%d\n", find1(root, b));
        if(a == 4) printf("%d\n", find2(root, b));
        if(a == 5)
        {
            find3(root, b);
            printf("%d\n", ans);
        }
        if(a == 6)
        {
            find4(root, b);
            printf("%d\n", ans);
        }
    }
    return 0;
}

跑的也不算慢,没开O2是168ms。
fhq treap不会写,不知道什么时候才能填上这个坑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值