1. 程式人生 > 其它 >P3369 【模板】普通平衡樹

P3369 【模板】普通平衡樹

【模板】普通平衡樹

題目描述

您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作: 1. 插入 $x$ 數 2. 刪除 $x$ 數(若有多個相同的數,因只刪除一個) 3. 查詢 $x$ 數的排名(排名定義為比當前數小的數的個數 $+1$ ) 4. 查詢排名為 $x$ 的數 5. 求 $x$ 的前驅(前驅定義為小於 $x$,且最大的數) 6. 求 $x$ 的後繼(後繼定義為大於 $x$,且最小的數)

輸入輸出格式

輸入格式

第一行為 $n$,表示操作的個數,下面 $n$ 行每行有兩個數 $\text{opt}$ 和 $x$,$\text{opt}$ 表示操作的序號( $ 1 \leq \text{opt} \leq 6 $ )

輸出格式

對於操作 $3,4,5,6$ 每行輸出一個數,表示對應答案

輸入輸出樣例

輸入樣例 #1

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

輸出樣例 #1

106465
84185
492737

說明

【資料範圍】 對於 $100\%$ 的資料,$1\le n \le 10^5$,$|x| \le 10^7$

FHQ(分裂式Treap)實現



#include <bits/stdc++.h>

using namespace std;

#define getsize(x) (x ? x -> size : 0) 

#define ll long long

const int MAXN = 1e5 + 10;

class FHQ
{
    public :
        class Node
        {
            public :
                int key, rank;
                int size;
                Node *ls, *rs;
                void push_up()
                {
                    size = getsize(ls) + getsize(rs) + 1;
                }
        }pool[2 * MAXN], *rt;

        int top;
        //分裂 p 返回 p 的左子p_l, 右子p_r
        void split(Node *p , Node *&p_l, Node *&p_r, int x)//分裂當前子樹
        {
            if(!p)//p 為空,無需分離
            {
                p_l = p_r = NULL;
                return ;
            }

            if(p -> key <= x)//如果 p 的值比 x 小,就把 p 接到左子上,繼續分裂 p 的右子
            {
                p_l = p;
                split(p -> rs, p_l -> rs, p_r, x);
                p_l -> push_up();
            }

            else//否則分 p 的左子
            {
                p_r = p;
                split(p -> ls, p_l ,p_r -> ls, x);
                p_r -> push_up();
            }

        }

        void merge(Node *&p, Node *p_l, Node *p_r)
        {
            if(!p_l || !p_r)//如果有一為空
            {
                p = p_l ? p_l : p_r;
                return ;
            }

            if(p_l -> rank < p_r -> rank)//維護平衡
            {
                p = p_l;
                merge(p -> rs, p_l -> rs, p_r);
            }

            else
            {
                p = p_r;
                merge(p -> ls, p_l, p_r -> ls);
            }
            p -> push_up();
        }

        Node *newNode(int x)
        {
            Node *p = pool + (++top);
            p -> key = x;
            p -> rank = rand();
            p -> size = 1;
            return p;
        }

        void insert(Node *&rt, int x)
        {
            Node *p1, *p2;
            split(rt, p1, p2 ,x - 1);
            merge(rt, p1 ,newNode(x));
            merge(rt, rt, p2);
        }

        void remove(Node *&rt, int x)
        {
            Node *p1, *p2, *p3 , *p4;
            split(rt, p1 ,p2 ,x - 1);
            split(p2, p3 ,p4, x);
            merge(p3, p3 -> ls, p3 -> rs);
            merge(p3, p3, p4);
            merge(rt, p1, p3);
        }

        int getRank(Node *&rt, int x)
        {
            Node *p1 ,*p2;
            split(rt, p1 ,p2, x - 1);

            int ans = getsize(p1);
            merge(rt, p1 ,p2);
            return ans;
        }

        int getKey(Node *p, int rank)
        {
            while(p)
            {
                if(rank <= getsize(p -> ls))
                    p = p -> ls;
                else if(rank > getsize(p -> ls) + 1)
                {
                    rank -= getsize(p -> ls) + 1;
                    p = p -> rs;
                }
                else return p -> key;
            }
            return 0;
        }

        int lower(Node *p, int x)
        {
            int ans = INT_MIN;
            while(p)
            {
                if(x > p -> key)
                {
                    ans = max(ans, p -> key);
                    p = p -> rs;
                }
                else p = p -> ls;
            }
            return ans;
        }

        int upper(Node *p, int x)
        {
            int ans = INT_MAX;
            while(p)
            {
                if(x < p -> key)
                {
                    ans = min(ans, p -> key);
                    p = p -> ls;
                }
                else p = p -> rs;
            }
            return ans;
        }

}FHQ;

int t;

int op, x;

int main()
{
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d %d", &op, &x);

        if(op == 1)
        {
            FHQ.insert(FHQ.rt, x);
        }

        if(op == 2)
        {
            FHQ.remove(FHQ.rt, x);
        }
        if(op == 3)
        {
            printf("%d\n", FHQ.getRank(FHQ.rt, x) + 1);
        }

        if(op == 4)
        {
            printf("%d\n", FHQ.getKey(FHQ.rt, x));
        }

        if(op == 5)
        {
            printf("%d\n" , FHQ.lower(FHQ.rt, x));
        }
        if(op == 6)
        {
            printf("%d\n", FHQ.upper(FHQ.rt, x));
        }

    }

    return 0;
}