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

洛谷P3369【模板】普通平衡樹

names 實現 oid for printf namespace treenode ret 找到

\(fhq-treap\)實現。

正文部分

\(fhq-treap\)的所有操作都在兩個\(split\)的基礎上,一次\(val\),一次\(size\)
註意:這裏我們是將小於等於操作數的值分為一棵樹,其余分為另一棵樹
分離和合並的過程很簡單,學的話可以看我的代碼手動模擬一下,這個過程應該不是很難。
對於一個數\(x\)的插入,我們先已這個值分一次\(val\),然後創建新節點和並即可。
對於一個數\(x\)的刪除,我們先已\(x\)分一次\(val\),然後在分出來的左子樹裏已\(x-1\)分一次\(val\),最後產生的右子樹我們將其左右孩子合並即可。
對於一個數\(x\)的排名,我們將其以\(x-1\)

分一次\(val\),然後輸出左子樹的\(size+1\)即可
對於找到排名為\(x\)的數,我們直接求一次\(kth\)就好了
對於求\(x\)的前驅,我們將其已\(x-1\)分一次\(val\),然後在左子樹裏找到\(kth\)為左子樹的\(size\)的節點就好了
對於求\(x\)的後續,我們已\(x\)分一次\(val\),然後在右子樹裏找到\(kth\)\(1\)的節點即可

My Code:

#include <bits/stdc++.h>
#define il inline
#define temp template<class T>
const int MAXN = 1e5 + 10;
using namespace std;
temp il void rd(T& res) {
    res = 0;char c;bool sign = 0;
    for(c = getchar();!isdigit(c);c = getchar()) sign |= c == ‘-‘;
    for(;isdigit(c);c = getchar()) res = (res << 1) + (res << 3) + (c ^ 48);
    (sign) && (res = -res);
    return; 
}
struct TreeNode {
    int ch[2],size,val,rnd;           
}tr[MAXN];
int n,m,i,j,k,q,cnt,root,y,z;
il int NewNode(int v) {
    tr[++cnt].size = 1;
    tr[cnt].val = v;tr[cnt].rnd = rand();
    return cnt;
}
il void pushup(int o) {
    tr[o].size = tr[tr[o].ch[0]].size + tr[tr[o].ch[1]].size + 1;
    return;
}
int merge(int u,int v) {
    if(!u) return v;if(!v) return u;
    if(tr[u].rnd < tr[v].rnd) {
        tr[u].ch[1] = merge(tr[u].ch[1],v);
        pushup(u);
        return u;
    } else {
        tr[v].ch[0] = merge(u,tr[v].ch[0]);
        pushup(v);
        return v;
    }
}
void split_v(int now,int k,int& x,int& y) {
    if(!now) x = y = 0;
    else {
        if(tr[now].val <= k) x = now,split_v(tr[now].ch[1],k,tr[now].ch[1],y);
        else y = now,split_v(tr[now].ch[0],k,x,tr[now].ch[0]);
        pushup(now);
    }   
    return;
}
il int kth(int u,int k) {
    while(1) {
        if(k <= tr[tr[u].ch[0]].size) {
            u = tr[u].ch[0];
        } else {
            if(k == tr[tr[u].ch[0]].size + 1) return u;
            k -= tr[tr[u].ch[0]].size + 1;u = tr[u].ch[1];
        }
    }
}
int main() {
    srand((unsigned)time(NULL));
    rd(q);
    while(q--) {
        int opt,x;rd(opt);rd(x);
        if(opt == 1) {
            split_v(root,x,y,z);
            root = merge(merge(y,NewNode(x)),z);
        } else if(opt == 2) {
            int k;
            split_v(root,x,y,k);
            split_v(y,x - 1,y,z);
            z = merge(tr[z].ch[0],tr[z].ch[1]);
            root = merge(y,merge(z,k)); 
        } else if(opt == 3) {
            split_v(root,x - 1,y,z);
            printf("%d\n",tr[y].size + 1);
            root = merge(y,z);      
        } else if(opt == 4) {
            printf("%d\n",tr[kth(root,x)].val);    
        } else if(opt == 5) {
            split_v(root,x - 1,y,z);        
            printf("%d\n",tr[kth(y,tr[y].size)].val);    
            root = merge(y,z);    
        } else {
            split_v(root,x,y,z);
            printf("%d\n",tr[kth(z,1)].val);
            root = merge(y,z);
        }
    }
    return 0;
}

洛谷P3369【模板】普通平衡樹