二次联通门 : P3369 【模板】普通平衡树(Treap/SBT)
/* luogu P3369 【模板】普通平衡树(Treap/SBT) splay 模板 支持插入x数 删除x数(若有多个相同的数,因只删除一个) 查询x数的排名(若有多个相同的数,因输出最小的排名) 查询排名为x的数 求x的前驱(前驱定义为小于x,且最大的数) 求x的后继(后继定义为大于x,且最小的数) */ #include <cstdio> #define Max 200005 void read (int &now) { now = 0; register char word = getchar (); bool temp = false; while (word < ‘0‘ || word > ‘9‘) { if (word == ‘-‘) temp = true; word = getchar (); } while (word <= ‘9‘ && word >= ‘0‘) { now = now * 10 + word - ‘0‘; word = getchar (); } if (temp) now = -now; } class Splay_Tree_Type { private: struct Tree_Date { int weigth; int size; int key; int child[2]; int father; } tree[Max]; inline int Get_Son (int now) { return tree[tree[now].father].child[1] == now; } int Count; int Root; public : inline void Update (int now) { tree[now].size = tree[now].weigth; if (tree[now].child[0]) tree[now].size += tree[tree[now].child[0]].size; if (tree[now].child[1]) tree[now].size += tree[tree[now].child[1]].size; } inline void Rotate (int now) { int father = tree[now].father; int Grand = tree[father].father; int pos = Get_Son (now); tree[father].child[pos] = tree[now].child[pos ^ 1]; tree[tree[father].child[pos]].father = father; tree[now].child[pos ^ 1] = father; tree[father].father = now; tree[now].father = Grand; if (Grand) tree[Grand].child[tree[Grand].child[1] == father] = now; Update (father); Update (now); } void Splay (int now) { for (int father; father = tree[now].father; Rotate (now)) if (tree[father].father) Rotate (Get_Son (now) == Get_Son (father) ? father : now); Root = now; } int Find_Prefix () { int now = tree[Root].child[0]; while (tree[now].child[1]) now = tree[now].child[1]; return now; } int Find_Suffix () { int now = tree[Root].child[1]; while (tree[now].child[0]) now = tree[now].child[0]; return now; } inline void Clear (int now) { tree[now].child[1] = 0; tree[now].child[1] = 1; tree[now].size = 0; tree[now].weigth = 0; tree[now].key = 0; tree[now].father = 0; } int Find_x_rank (int x) { int now = Root; int Answer = 0; while (true) { if (x < tree[now].key) { now = tree[now].child[0]; continue; } Answer += tree[now].child[0] ? tree[tree[now].child[0]].size : 0; if (tree[now].key == x) { Splay (now); return Answer + 1; } Answer += tree[now].weigth; now = tree[now].child[1]; } } int Find_rank_x (int x) { int now = Root; while (true) { if (tree[now].child[0] && x <= tree[tree[now].child[0]].size) { now = tree[now].child[0]; continue; } int temp = (tree[now].child[0] ? tree[tree[now].child[0]].size : 0) + tree[now].weigth; if (x <= temp) return tree[now].key; x -= temp; now = tree[now].child[1]; } } void Insert (int x) { if (!Root) { Count++; tree[Count].key = x; tree[Count].size = 1; tree[Count].weigth = 1; Root = Count; return; } int father = 0, now = Root; while (true) { if (tree[now].key == x) { tree[now].size++; tree[now].weigth++; Splay (now); return ; } father = now; now = tree[now].child[x > tree[father].key]; if (!now) { Count++; tree[father].child[x > tree[father].key] = Count; tree[Count].father = father; tree[Count].key = x; tree[Count].size = 1; tree[Count].weigth = 1; Splay (Count); return ; } } } void Delete (int x) { Find_x_rank (x); if (tree[Root].weigth > 1) { tree[Root].weigth--; tree[Root].size--; return ; } if (!tree[Root].child[0] && !tree[Root].child[1]) { Clear (Root); Root = 0; return ; } if (!tree[Root].child[0]) { int temp = Root; Root = tree[Root].child[1]; tree[Root].father = 0; Clear (temp); return ; } if (!tree[Root].child[1]) { int temp = Root; Root = tree[Root].child[0]; tree[Root].father = 0; Clear (temp); return ; } int Prefix = Find_Prefix (); int temp = Root; Splay (Prefix); tree[Root].child[1] = tree[temp].child[1]; tree[tree[temp].child[1]].father = Root; Clear (temp); Update (Root); } inline int Get_tree_value (int now) { return tree[now].key; } }; Splay_Tree_Type Splay_Tree; int main (int argc, char *argv[]) { int N; read (N); int type, x; for (; N--; ) { read (type); read (x); if (type == 1) Splay_Tree.Insert (x); else if (type == 2) Splay_Tree.Delete (x); else if (type == 3) printf ("%d\n", Splay_Tree.Find_x_rank (x)); else if (type == 4) printf ("%d\n", Splay_Tree.Find_rank_x (x)); else if (type == 5) // 因为不确定x是否在平衡树中, 那么先插入在查找可以防止这种情况的发生 { Splay_Tree.Insert (x); printf ("%d\n", Splay_Tree.Get_tree_value (Splay_Tree.Find_Prefix ())); Splay_Tree.Delete (x); } else { Splay_Tree.Insert (x); printf ("%d\n", Splay_Tree.Get_tree_value (Splay_Tree.Find_Suffix ())); Splay_Tree.Delete (x); } } return 0; }
时间: 2024-10-13 01:48:10