1. 程式人生 > >【模板】普通平衡樹(Treap/SBT)

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

gpo splay 格式 可能 bit bsp inf ron 表示

題目描述

您需要寫一種數據結構(可參考題目標題),來維護一些數,其中需要提供以下操作:

  1. 插入x數

  2. 刪除x數(若有多個相同的數,因只刪除一個)

  3. 查詢x數的排名(排名定義為比當前數小的數的個數+1。若有多個相同的數,因輸出最小的排名)

  4. 查詢排名為x的數

  5. 求x的前驅(前驅定義為小於x,且最大的數)

  6. 求x的後繼(後繼定義為大於x,且最小的數)

輸入輸出格式

輸入格式:

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

輸出格式:

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

#include <bits/stdc++.h>

using
namespace std; const int maxn = 100000+5; const int inf = 2000000008; int root,tot; struct Splay{ int ch[maxn][2],fa[maxn],siz[maxn],key[maxn], same[maxn]; void init(int t, int val = 0, int par = 0){ ch[t][0] = ch[t][1] = 0; key[t] = val;same[t] = 1; fa[t] = par; } void up(int t){ siz[t]
= siz[ch[t][1]] + siz[ch[t][0]] + same[t]; } void init(){ init(0, 0, 0); tot = root = 0; } void rotate(int x, int d){ int y = fa[x]; ch[y][d^1] = ch[x][d]; if(ch[x][d])fa[ch[x][d]] = y; fa[x] = fa[y]; if(fa[y]){ if(y == ch[fa[y]][0
])ch[fa[y]][0] = x; else ch[fa[y]][1] = x; } ch[x][d] = y;fa[y] = x; up(y); // father first up(x); } void splay(int x, int targrt){ while(fa[x] != targrt){ int y = fa[x]; if(x == ch[y][0]){ if(targrt != fa[y] && y == ch[fa[y]][0]) rotate(y, 1); rotate(x, 1); } else { if(targrt != fa[y]&& y == ch[fa[y]][1]) rotate(y, 0); rotate(x, 0); } } if(!targrt)root = x; } void insert( int x,int t = root, int par = 0){ if(!t){ t = ++tot; init(t, x, par); ch[par][x > key[par]] = t; splay(t, 0); } else{ if(x == key[t]){ same[t]++; up(t); //! } else if(x < key[t]){ insert(x, ch[t][0], t); up(t); } else { insert(x, ch[t][1], t); up(t); } } } int rank(int x,int t = root){ if(!t)return 0; if(x == key[t])return siz[ch[t][0]]+1; if(x < key[t])return rank(x, ch[t][0]); return siz[ch[t][0]]+same[t]+rank(x, ch[t][1]); } int query(int x, int t = root){ if(!x)return t; if(x > siz[ch[t][0]] + same[t]) return query(x - same[t] - siz[ch[t][0]], ch[t][1]); if(x <= siz[ch[t][0]])return query(x, ch[t][0]); return t; } void Query(int x){ printf("%d\n",key[query(x)]); } void erase(int x){ int t = root; while(key[t] != x)t = ch[t][x > key[t]]; splay(t, 0); if(same[t]>1){ same[t]--; up(t); //! return; } same[t] = 0; int y = ch[t][1]; bool b; if(!y)y = ch[root][0], b = 1; else b = 0; if(!y)root = 0,same[t] = 0;//有可能只有一個節點 while(ch[y][b])y = ch[y][b]; splay(y, root); ch[y][b] = ch[root][b]; if(ch[root][b]) fa[ch[root][b]] = y; fa[y] = 0; root = y; up(y); //! } int getpre(int x){ int ret = -inf, t = root; while(t){ if(key[t] < x)ret = max(ret, key[t]); t = ch[t][x > key[t]]; } return ret; } int getscc(int x){ int ret = inf, t = root; while(t){ if(key[t] > x) ret = min(ret, key[t]); t = ch[t][x >=key[t]]; } return ret; } void print(){ for(int i = 1; i <= tot; i++) printf("%d %d %d\n",i, ch[i][0], ch[i][1]); } }Tr; int main() { int n; scanf("%d",&n); Tr.init(); while(n--){ int opt,x; scanf("%d%d",&opt,&x); switch(opt){ case 1:Tr.insert(x);break; case 2:Tr.erase(x);break; case 3:printf("%d\n",Tr.rank(x));break; case 4:Tr.Query(x);break; case 5:printf("%d\n",Tr.getpre(x));break; case 6:printf("%d\n",Tr.getscc(x));break; } //Tr.print(); } return 0; }

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