二次联通门 : luogu P3369 【模板】普通平衡树(Treap/SBT)
近几天闲来无事。。。就把各种平衡树都写了一下。。。
下面是红黑树(Red Black Tree)
喜闻乐见拿到了luogu,COGS的rank1
QAQ rank1没啦!!!被树状数组艹啦!!!
10.11 Updata 压了压行233333
#include <cstdio> #include <iostream> #define Max 100001 #define Red true #define Black false const int BUF = 100000100; char Buf[BUF], *buf = Buf; #define rg register #define Inline __attri bute__( ( optimize( "-O2" ) ) ) Inline void read (int &n) { bool temp = false; for (n = 0; !isdigit (*buf); ++ buf) if (*buf == '-') temp = true; for (; isdigit (*buf); n = n * 10 + *buf - '0', ++ buf); if (temp) n = -n; } struct RD { int v, _s, _w; bool _c; RD *f, *c[2]; Inline void Fill (const int &_v, const bool &__c, const int &z, rg RD *n) { v = _v, _c = __c, _s = _w = z, f = c[0] = c[1] = n; } Inline void Up () { _s = c[0]->_s + c[1]->_s + _w; } Inline void dn () { for (RD *n = this; n->_s; n = n->f) -- n->_s; } Inline int Get_Pos (const int &n) { return this->v == n ? -1 : n > v; } }; class Red_Black_Tree { private : int _t; RD *Rt, *null, poor[Max], *Tail, *reuse[Max]; private : Inline RD *New (const int &v) { rg RD *n = null; if (!_t) n = Tail ++; else n = reuse[-- _t]; n->Fill (v, Red, 1, null); return n; } Inline void R (RD *&n, const bool &_p) { rg RD *C = n->c[_p ^ 1]; n->c[_p ^ 1] = C->c[_p]; if (C->c[_p]->_s) C->c[_p]->f = n; C->f = n->f; if (!n->f->_s) Rt = C; else n->f->c[n->f->c[0] != n] = C; C->c[_p] = n; n->f = C; C->_s = n->_s; n->Up (); } Inline void If (rg RD *&n) { for (; n->f->_c; ) { RD *_F = n->f, *_g = _F->f; bool _p = _F == _g->c[0]; RD *_u = _g->c[_p]; if (_u->_c) _F->_c = _u->_c = Black, _g->_c = Red, n = _g; else if (n == _F->c[_p]) R (n = _F, _p ^ 1); else _g->_c = Red, _F->_c = Black, R (_g, _p); } Rt->_c = Black; } Inline RD *Find (RD *n, int v) { for (; n->_s && n->v != v; n = n->c[n->v < v]); return n; } Inline void Df (rg RD *&n) { for (; n != Rt && n->_c == Black; ) { rg bool _p = n == n->f->c[0]; RD *_F = n->f, *_u = _F->c[_p]; if (_u->_c == Red) _u->_c = Black, _F->_c = Red, R (n->f, _p ^ 1), _u = _F->c[_p]; else if (_u->c[0]->_c == Black && _u->c[1]->_c == Black) _u->_c = Red, n = _F; else { if (_u->c[_p]->_c == Black) _u->c[_p ^ 1]->_c = Black, _u->_c = Red, R (_u, _p), _u = _F->c[_p]; _u->_c = _F->_c, _u->c[_p]->_c = _F->_c = Black, R (_F, _p ^ 1); break; } } n->_c = Black; } public : Red_Black_Tree () { _t = 0, Tail = &poor[_t]; null = Tail ++, null->Fill (0, Black, 0, NULL), Rt = null; } Inline void Insert (const int &v) { rg RD *n = Rt, *_F = null; rg int _p; for (; n->_s; n = n->c[_p]) { ++ n->_s, _F = n, _p = n->Get_Pos (v); if (_p == -1) { ++ n->_w; return ; } } n = New (v); if (_F->_s) _F->c[v > _F->v] = n; else Rt = n; n->f = _F; If (n); } Inline void Delete (const int &v) { rg RD *_r = Find (Rt, v); if (!_r->_s) return ; if (_r->_w > 1) { -- _r->_w, _r->dn (); return ; } rg RD *_F = _r, *n = null; if (_r->c[0]->_s && _r->c[1]->_s) for (_F = _r->c[1]; _F->c[0]->_s; _F = _F->c[0]); n = _F->c[!_F->c[0]->_s], n->f = _F->f; if (!_F->f->_s) Rt = n; else _F->f->c[_F->f->c[1] == _F] = n; if (_r != _F) _r->v = _F->v, _r->_w = _F->_w; _F->f->dn (); for (RD *p = _F->f; _F->_w > 1 && p->_s && p != _r; p->_s -= _F->_w - 1, p = p->f); if (_F->_c == Black) Df (n); reuse[_t ++] = _F; } Inline int Get_kth_number (rg int k) { rg int _r; rg RD *n = Rt; for (; n->_s; ) { _r = n->c[0]->_s; if (k <= _r) n = n->c[0]; else if (_r + 1 <= k && k <= _r + n->_w) break; else k -= _r + n->_w, n = n->c[1]; } return n->v; } Inline int Get_rank (const int &v) { rg int _r, cur = 0; rg RD *n = Rt; for (; n->_s; ) { _r = n->c[0]->_s; if (n->v == v) break; else if (n->v > v) n = n->c[0]; else cur += _r + n->_w, n = n->c[1]; } return cur + _r + 1; } Inline int Find_Suffix (const int &v) { rg int _r = 0; for (RD *n = Rt; n->_s; ) if (n->v > v) _r = n->v, n = n->c[0]; else n = n->c[1]; return _r; } Inline int Find_Prefix (const int &v) { rg int _r = 0; for (RD *n = Rt; n->_s; ) if (n->v < v) _r = n->v, n = n->c[1]; else n = n->c[0]; return _r; } }; Red_Black_Tree Rbt; void write_ (int n) { if (n > 9) write_ (n / 10); putchar (n % 10 + '0'); } inline void write (int n) { if (n < 0) putchar ('-'), n = -n; write_ (n); putchar (' '); } int Main () { fread (buf, 1, BUF, stdin); int N; read (N); for (int type, x; N --; ) { read (type); read (x); if (type == 1) Rbt.Insert (x); else if (type == 2) Rbt.Delete (x); else if (type == 3) write (Rbt.Get_rank (x)); else if (type == 4) write (Rbt.Get_kth_number (x)); else if (type == 5) write (Rbt.Find_Prefix (x)); else write (Rbt.Find_Suffix (x)); } return 0; } int ZlycerQan = Main(); int main(int argc, char *argv[]){;}
#include <cstdio> #include <iostream> #define Max 100001 #define Red true #define Black false const int BUF = 100000100; char Buf[BUF], *buf = Buf; #define Inline __attri bute__( ( optimize( "-O2" ) ) ) Inline void read (int &now) { int temp = 0; for (now = 0; !isdigit (*buf); ++ buf) if (*buf == '-') temp = 1; for (; isdigit (*buf); now = now * 10 + *buf - '0', ++ buf); if (temp) now = -now; } struct R_D { int key, size, weigth; bool color; R_D *father, *child[2]; Inline void Fill (const int &__key, const bool &__color, const int &z, register R_D *now) { this->key = __key; this->color = __color; this->size = this->weigth = z; this->father = this->child[0] = this->child[1] = now; } Inline void Up () { this->size = this->child[0]->size + this->child[1]->size + this->weigth; } Inline void Down () { for (R_D *now = this; now->size; now = now->father) now->size --; } Inline int Get_Pos (const int &now) const { return this->key == now ? -1 : now > this->key; } }; class Red_Black_Tree { private : int Top; R_D *Root, *null; R_D poor[Max], *Tail, *reuse[Max]; Inline R_D *New (const int &key) { register R_D *now = null; if (!Top) now = Tail ++; else now = reuse[-- Top]; now->Fill (key, Red, 1, null); return now; } Inline void Rotate (R_D *&now, const bool &pos) { register R_D *C = now->child[pos ^ 1]; now->child[pos ^ 1] = C->child[pos]; if (C->child[pos]->size) C->child[pos]->father = now; C->father = now->father; if (!now->father->size) Root = C; else now->father->child[now->father->child[0] != now] = C; C->child[pos] = now; now->father = C; C->size = now->size; now->Up (); } Inline void Insert_Fill (register R_D *&now) { for (; now->father->color; ) { R_D *Father = now->father, *Grand = Father->father; bool pos = Father == Grand->child[0]; R_D *Uncle = Grand->child[pos]; if (Uncle->color) { Father->color = Uncle->color = Black; Grand->color = Red; now = Grand; } else if (now == Father->child[pos]) Rotate (now = Father, pos ^ 1); else { Grand->color = Red; Father->color = Black; Rotate (Grand, pos); } } Root->color = Black; } Inline R_D *Find (R_D *now, int key) { for (; now->size && now->key != key; now = now->child[now->key < key]); return now; } Inline void Delete_Fill (register R_D *&now) { for (; now != Root && now->color == Black; ) { register bool pos = now == now->father->child[0]; R_D *Father = now->father, *Uncle = Father->child[pos]; if (Uncle->color == Red) { Uncle->color = Black; Father->color = Red; Rotate (now->father, pos ^ 1); Uncle = Father->child[pos]; } else if (Uncle->child[0]->color == Black && Uncle->child[1]->color == Black) { Uncle->color = Red; now = Father; } else { if (Uncle->child[pos]->color == Black) { Uncle->child[pos ^ 1]->color = Black; Uncle->color = Red; Rotate (Uncle, pos); Uncle = Father->child[pos]; } Uncle->color = Father->color; Uncle->child[pos]->color = Father->color = Black; Rotate (Father, pos ^ 1); break; } } now->color = Black; } public : Red_Black_Tree () { Top = 0; Tail = &poor[Top]; null = Tail ++; null->Fill (0, Black, 0, NULL); Root = null; } Inline void Insert (const int &key) { register R_D *now = Root, *Father = null; register int pos; for (; now->size; now = now->child[pos]) { now->size ++; Father = now; pos = now->Get_Pos (key); if (pos == -1) { now->weigth ++; return ; } } now = New (key); if (Father->size) Father->child[key > Father->key] = now; else Root = now; now->father = Father; this->Insert_Fill (now); } Inline void Delete (const int &key) { register R_D *res = Find (Root, key); if (!res->size) return ; if (res->weigth > 1) { res->weigth --; res->Down (); return ; } register R_D *Father = res, *now = null; if (res->child[0]->size && res->child[1]->size) for (Father = res->child[1]; Father->child[0]->size; Father = Father->child[0]); now = Father->child[!Father->child[0]->size]; now->father = Father->father; if (!Father->father->size) Root = now; else Father->father->child[Father->father->child[1] == Father] = now; if (res != Father) { res->key = Father->key; res->weigth = Father->weigth; } Father->father->Down (); for (R_D *Fuck = Father->father; Father->weigth > 1 && Fuck->size && Fuck != res; Fuck->size -= Father->weigth - 1, Fuck = Fuck->father); if (Father->color == Black) Delete_Fill (now); reuse[Top ++] = Father; } Inline int Get_kth_number (register int k) { register int res; register R_D *now = Root; for (; now->size; ) { res = now->child[0]->size; if (k <= res) now = now->child[0]; else if (res + 1 <= k && k <= res + now->weigth) break; else { k -= res + now->weigth; now = now->child[1]; } } return now->key; } Inline int Get_rank (const int &key) { register int res, cur = 0; register R_D *now = Root; for (; now->size; ) { res = now->child[0]->size; if (now->key == key) break; else if (now->key > key) now = now->child[0]; else { cur += res + now->weigth; now = now->child[1]; } } return cur + res + 1; } Inline int Find_Suffix (const int &key) { register int res = 0; for (R_D *now = Root; now->size; ) if (now->key > key) { res = now->key; now = now->child[0]; } else now = now->child[1]; return res; } Inline int Find_Prefix (const int &key) { register int res = 0; for (R_D *now = Root; now->size; ) if (now->key < key) { res = now->key; now = now->child[1]; } else now = now->child[0]; return res; } }; Red_Black_Tree Rbt; void write_ (int now) { if (now > 9) write_ (now / 10); putchar (now % 10 + '0'); } inline void write (int now) { if (now < 0) putchar ('-'), now = -now; write_ (now); putchar (' '); } int N; int Main () { fread (buf, 1, BUF, stdin); read (N); for (int type, x; N --; ) { read (type); read (x); switch (type) { case 1: Rbt.Insert (x); break; case 2: Rbt.Delete (x); break; case 3: write (Rbt.Get_rank (x)); break; case 4: write (Rbt.Get_kth_number (x)); break; case 5: write (Rbt.Find_Prefix (x)); break; case 6: write (Rbt.Find_Suffix (x)); break; } } return 0; } int ZlycerQan = Main(); int main(int argc, char *argv[]){;}