lct.hpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <cassert> | ||
| 4 | #include <utility> | ||
| 5 | |||
| 6 | namespace lct { | ||
| 7 | |||
| 8 | struct node { | ||
| 9 | node* p; | ||
| 10 | node* c[2]; | ||
| 11 | |||
| 12 | int s; | ||
| 13 | |||
| 14 | bool flip; | ||
| 15 | |||
| 16 | // isroot | ||
| 17 | ✗ | inline bool r() { return p == nullptr || !(this == p->c[0] || this == p->c[1]); } | |
| 18 | // direction | ||
| 19 | ✗ | inline bool d() { assert(!r()); return this == p->c[1]; } | |
| 20 | |||
| 21 | ✗ | inline void update() { s = 1 + (c[0] ? c[0]->s : 0) + (c[1] ? c[1]->s : 0); } | |
| 22 | ✗ | void propogate() { | |
| 23 | ✗ | if(flip) { | |
| 24 | ✗ | std::swap(c[0], c[1]); | |
| 25 | ✗ | if(c[0]) c[0]->flip = !c[0]->flip; | |
| 26 | ✗ | if(c[1]) c[1]->flip = !c[1]->flip; | |
| 27 | ✗ | flip = false; | |
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | // precondition: parent and current are propogated | ||
| 32 | ✗ | void rot() { | |
| 33 | ✗ | assert(!r()); | |
| 34 | |||
| 35 | ✗ | int x = d(); | |
| 36 | ✗ | node* pa = p; | |
| 37 | ✗ | node* ch = c[!x]; | |
| 38 | |||
| 39 | ✗ | assert(!pa->flip); | |
| 40 | ✗ | assert(!flip); | |
| 41 | |||
| 42 | ✗ | assert((!ch) || ch->p == this); | |
| 43 | |||
| 44 | ✗ | if(!pa->r()) pa->p->c[pa->d()] = this; | |
| 45 | ✗ | this->p = pa->p; | |
| 46 | |||
| 47 | ✗ | pa->c[x] = ch; | |
| 48 | ✗ | if(ch) ch->p = pa; | |
| 49 | |||
| 50 | ✗ | this->c[!x] = pa; | |
| 51 | ✗ | pa->p = this; | |
| 52 | |||
| 53 | ✗ | pa->update(); | |
| 54 | ✗ | update(); | |
| 55 | } | ||
| 56 | |||
| 57 | // postcondition: always propogated | ||
| 58 | ✗ | void splay() { | |
| 59 | ✗ | if(r()) { | |
| 60 | ✗ | update(); | |
| 61 | ✗ | propogate(); | |
| 62 | ✗ | return; | |
| 63 | } | ||
| 64 | |||
| 65 | ✗ | while(!r()) { | |
| 66 | ✗ | if(!p->r()) { | |
| 67 | ✗ | node* gp = p->p; | |
| 68 | ✗ | node* pa = p; | |
| 69 | ✗ | gp->propogate(); | |
| 70 | ✗ | pa->propogate(); | |
| 71 | ✗ | propogate(); | |
| 72 | ✗ | if(d() == p->d()) { | |
| 73 | ✗ | pa->rot(); | |
| 74 | ✗ | assert(p == pa); | |
| 75 | } else { | ||
| 76 | ✗ | rot(); | |
| 77 | ✗ | assert(p == gp); | |
| 78 | } | ||
| 79 | ✗ | rot(); | |
| 80 | } else { | ||
| 81 | ✗ | p->propogate(); | |
| 82 | ✗ | propogate(); | |
| 83 | ✗ | rot(); | |
| 84 | ✗ | assert(r()); | |
| 85 | } | ||
| 86 | } | ||
| 87 | ✗ | update(); | |
| 88 | } | ||
| 89 | |||
| 90 | // attach on right side | ||
| 91 | // precondition: propogated | ||
| 92 | ✗ | void make_child(node* n) { | |
| 93 | ✗ | assert(!flip); | |
| 94 | ✗ | assert(r()); | |
| 95 | |||
| 96 | ✗ | if(c[1]) { | |
| 97 | ✗ | node* v = c[1]; | |
| 98 | ✗ | c[1] = nullptr; | |
| 99 | ✗ | assert(v->r()); | |
| 100 | |||
| 101 | ✗ | update(); | |
| 102 | } | ||
| 103 | |||
| 104 | ✗ | assert(!flip); | |
| 105 | ✗ | assert(!c[1]); | |
| 106 | |||
| 107 | ✗ | if(n) { | |
| 108 | |||
| 109 | ✗ | assert(n->r()); | |
| 110 | ✗ | assert(n->p == this); | |
| 111 | |||
| 112 | ✗ | c[1] = n; | |
| 113 | ✗ | assert(c[1]->p == this); | |
| 114 | |||
| 115 | ✗ | update(); | |
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | // postcondition: propogated | ||
| 120 | ✗ | void expose() { | |
| 121 | ✗ | splay(); | |
| 122 | ✗ | assert(!flip); | |
| 123 | ✗ | make_child(nullptr); | |
| 124 | ✗ | while(p) { | |
| 125 | ✗ | assert(r()); | |
| 126 | ✗ | p->splay(); | |
| 127 | ✗ | p->make_child(this); | |
| 128 | ✗ | assert(!p->flip); | |
| 129 | ✗ | assert(!flip); | |
| 130 | ✗ | rot(); | |
| 131 | ✗ | update(); | |
| 132 | ✗ | assert(r()); | |
| 133 | } | ||
| 134 | ✗ | assert(!p); | |
| 135 | ✗ | assert(!c[1]); | |
| 136 | } | ||
| 137 | |||
| 138 | // does not propogate | ||
| 139 | ✗ | void make_root() { | |
| 140 | ✗ | expose(); | |
| 141 | ✗ | assert(p == nullptr); | |
| 142 | ✗ | assert(r()); | |
| 143 | ✗ | flip = !flip; | |
| 144 | } | ||
| 145 | |||
| 146 | }; | ||
| 147 | |||
| 148 | } // namespace lct | ||
| 149 |