|
| 1 | + |
| 2 | +/** Which of the favors of your Lord will you deny ? **/ |
| 3 | + |
| 4 | +#include<bits/stdc++.h> |
| 5 | +using namespace std; |
| 6 | + |
| 7 | +#define LL long long |
| 8 | +#define PII pair<int,int> |
| 9 | +#define PLL pair<LL,LL> |
| 10 | +#define F first |
| 11 | +#define S second |
| 12 | + |
| 13 | +#define ALL(x) (x).begin(), (x).end() |
| 14 | +#define READ freopen("alu.txt", "r", stdin) |
| 15 | +#define WRITE freopen("vorta.txt", "w", stdout) |
| 16 | + |
| 17 | +#ifndef ONLINE_JUDGE |
| 18 | +#define DBG(x) cout << __LINE__ << " says: " << #x << " = " << (x) << endl |
| 19 | +#else |
| 20 | +#define DBG(x) |
| 21 | +#define endl "\n" |
| 22 | +#endif |
| 23 | + |
| 24 | +#define left 0 |
| 25 | +#define right 1 |
| 26 | + |
| 27 | +struct Node |
| 28 | +{ |
| 29 | + int data,color; |
| 30 | + Node *child[2]; |
| 31 | + |
| 32 | + Node(int data,int color) |
| 33 | + { |
| 34 | + this->data = data; |
| 35 | + this->color = color; |
| 36 | + this->child[left] = NULL; |
| 37 | + this->child[right] = NULL; |
| 38 | + } |
| 39 | +}; |
| 40 | + |
| 41 | +#define RED 0 |
| 42 | +#define BLACK 1 |
| 43 | + |
| 44 | +/// Red - 0 , Black - 1 |
| 45 | + |
| 46 | +struct RBT |
| 47 | +{ |
| 48 | + Node *root; |
| 49 | + |
| 50 | + RBT() |
| 51 | + { |
| 52 | + root = NULL; |
| 53 | + } |
| 54 | + |
| 55 | + bool red(Node *node) |
| 56 | + { |
| 57 | + if(node==NULL) |
| 58 | + return false; |
| 59 | + |
| 60 | + return node->color == RED; |
| 61 | + } |
| 62 | + |
| 63 | + void colorFlip(Node *node) |
| 64 | + { |
| 65 | + node->color = node->color^1; |
| 66 | + node->child[left]->color = node->child[left]->color^1; |
| 67 | + node->child[right]->color = node->child[right]->color^1; |
| 68 | + } |
| 69 | + |
| 70 | + Node* rotate(Node *node,bool dir) |
| 71 | + { |
| 72 | + Node *temp = node->child[!dir]; |
| 73 | + node->child[!dir] = temp->child[dir]; |
| 74 | + temp->child[dir] = node; |
| 75 | + |
| 76 | + temp->color = node->color; |
| 77 | + node->color = RED; |
| 78 | + |
| 79 | + return temp; |
| 80 | + } |
| 81 | + |
| 82 | + /// align reds , then rotate |
| 83 | + Node* doubleRotate(Node *node,bool dir) |
| 84 | + { |
| 85 | + node->child[!dir] = rotate(node->child[!dir],!dir); |
| 86 | + return rotate(node,dir); |
| 87 | + } |
| 88 | + |
| 89 | + void insert(int data) |
| 90 | + { |
| 91 | + root = __insert(root,data); |
| 92 | + root->color = BLACK; |
| 93 | + } |
| 94 | + |
| 95 | + Node* INSERT_FIX_UP(Node *node,bool dir) |
| 96 | + { |
| 97 | + if(red(node->child[dir])) |
| 98 | + { |
| 99 | + /// case 1 : both child red => any one child has 2 reds in a row (LL LR RR RL) => flip colors |
| 100 | + if(red(node->child[!dir])) |
| 101 | + { |
| 102 | + if(red(node->child[dir]->child[dir]) || red(node->child[dir]->child[!dir])) |
| 103 | + { |
| 104 | + colorFlip(node); |
| 105 | + } |
| 106 | + } |
| 107 | + else |
| 108 | + { |
| 109 | + /// case 2 : both child not red |
| 110 | + |
| 111 | + if(red(node->child[dir]->child[dir])) |
| 112 | + { |
| 113 | + /// any one child has 2 reds in a row (LL RR) => rotate |
| 114 | + node = rotate(node,!dir); |
| 115 | + } |
| 116 | + else if(red(node->child[dir]->child[!dir])) |
| 117 | + { |
| 118 | + /// any one child has 2 reds in a row (LR RL) => align first , then rotate |
| 119 | + node = doubleRotate(node,!dir); |
| 120 | + } |
| 121 | + } |
| 122 | + } |
| 123 | + return node; |
| 124 | + } |
| 125 | + |
| 126 | + Node* __insert(Node *node,int data) |
| 127 | + { |
| 128 | + if(node == NULL) |
| 129 | + return new Node(data,RED); |
| 130 | + |
| 131 | + bool dir = data > node->data; /// left -> 0 , right -> 1 |
| 132 | + node->child[dir] = __insert(node->child[dir],data); |
| 133 | + |
| 134 | + return INSERT_FIX_UP(node,dir); |
| 135 | + } |
| 136 | + |
| 137 | + bool search(int data) |
| 138 | + { |
| 139 | + Node* ret = search(root,data); |
| 140 | + |
| 141 | + if(ret==NULL) |
| 142 | + return false; |
| 143 | + else |
| 144 | + return true; |
| 145 | + } |
| 146 | + |
| 147 | + Node* search(Node* node,int data) |
| 148 | + { |
| 149 | + if(node == NULL || node->data==data) |
| 150 | + return node; |
| 151 | + |
| 152 | + bool dir = data > node->data; |
| 153 | + |
| 154 | + return search(node->child[dir],data); |
| 155 | + } |
| 156 | + |
| 157 | + void preorder() |
| 158 | + { |
| 159 | +// cout<<"Preorder : "; |
| 160 | + preorder(root); |
| 161 | + cout<<endl; |
| 162 | + } |
| 163 | + |
| 164 | + void preorder(Node *node) |
| 165 | + { |
| 166 | + if(node == NULL) |
| 167 | + return; |
| 168 | + |
| 169 | + cout<<node->data<<":"<<(node->color==RED ? "r":"b"); |
| 170 | + |
| 171 | + if(node->child[left] || node->child[right]) |
| 172 | + cout<<"("; |
| 173 | + preorder(node->child[left]); |
| 174 | + if(node->child[left] || node->child[right]) |
| 175 | + cout<<")"; |
| 176 | + |
| 177 | + if(node->child[left] || node->child[right]) |
| 178 | + cout<<"("; |
| 179 | + preorder(node->child[right]); |
| 180 | + if(node->child[left] || node->child[right]) |
| 181 | + cout<<")"; |
| 182 | + } |
| 183 | + |
| 184 | + void delete_(int data) |
| 185 | + { |
| 186 | + bool ok = false; |
| 187 | + root = __delete(root,data,ok); |
| 188 | + if(root!=NULL) |
| 189 | + root->color = BLACK; |
| 190 | + } |
| 191 | + |
| 192 | + Node* __delete(Node *node,int data,bool &ok) |
| 193 | + { |
| 194 | + if(node == NULL) |
| 195 | + { |
| 196 | + cout<<"NULL"<<endl; |
| 197 | + ok = true; |
| 198 | + } |
| 199 | + else |
| 200 | + { |
| 201 | + /// found the delete key |
| 202 | + if(node->data == data) |
| 203 | + { |
| 204 | + /// has one child only |
| 205 | + if(node->child[left]==NULL || node->child[right]==NULL) |
| 206 | + { |
| 207 | + Node* temp = NULL; |
| 208 | + if(node->child[left]) |
| 209 | + temp = node->child[left]; |
| 210 | + if(node->child[right]) |
| 211 | + temp = node->child[right]; |
| 212 | + |
| 213 | + |
| 214 | + if(red(node)) /// the node is red => just delete it |
| 215 | + { |
| 216 | + free(node); |
| 217 | + ok = true; |
| 218 | + } |
| 219 | + else if(red(temp)) /// only child is red => replace with that red child and recolor black . so , black balance restored |
| 220 | + { |
| 221 | + temp->color = BLACK; |
| 222 | + free(node); |
| 223 | + ok = true; |
| 224 | + } |
| 225 | + |
| 226 | + return temp; |
| 227 | + } |
| 228 | + else /// has 2 child => replace with inorder predecessor / successor and recurse for that |
| 229 | + { |
| 230 | + Node *temp = getMax(node->child[left]); /// inorder predecessor : maximum value in the left subtree |
| 231 | + |
| 232 | + node->data = temp->data; |
| 233 | + data = temp->data; /// updating with predecessor data as this is the one to delete now |
| 234 | + } |
| 235 | + } |
| 236 | + |
| 237 | + |
| 238 | + bool dir = data > node->data; |
| 239 | + |
| 240 | + node->child[dir] = __delete(node->child[dir],data,ok); /// recurse |
| 241 | + |
| 242 | + if(ok==false) |
| 243 | + { |
| 244 | + node = DELETE_FIX_UP(node,dir,ok); |
| 245 | + } |
| 246 | + } |
| 247 | + |
| 248 | + return node; |
| 249 | + } |
| 250 | + |
| 251 | + Node* DELETE_FIX_UP(Node *node,bool dir, bool &ok) |
| 252 | + { |
| 253 | + Node *parent = node; /// saving for later red sibling fixing case |
| 254 | + Node *sibling = node->child[!dir]; |
| 255 | + |
| 256 | + /// Case 1 : Red Sibling => Reduce to deterministic Black Sibling Case |
| 257 | + if(red(sibling)) |
| 258 | + { |
| 259 | + node = rotate(node,dir); |
| 260 | + sibling = parent->child[!dir]; |
| 261 | + } |
| 262 | + |
| 263 | + if(sibling != NULL) |
| 264 | + { |
| 265 | + /// Case 2 Part 1 : Black Sibling with only black children |
| 266 | + if(!red(sibling->child[left]) && !red(sibling->child[right])) |
| 267 | + { |
| 268 | + if(red(parent)) |
| 269 | + ok = true; /// will color it black and sibling subtree will not have imbalance |
| 270 | + |
| 271 | + parent->color = BLACK; /// if not ok , it will mean DOUBLE BLACK edge |
| 272 | + sibling->color = RED; |
| 273 | + } |
| 274 | + else /// Case 2 Part 2 : Black Sibling with not all black children |
| 275 | + { |
| 276 | + |
| 277 | + int initcol_parent = parent->color; |
| 278 | + bool isRedSiblingReduction = !(node==parent); |
| 279 | + |
| 280 | + if(red(sibling->child[!dir])) /// RR , LL |
| 281 | + { |
| 282 | + parent = rotate(parent,dir); /// single rotation |
| 283 | + } |
| 284 | + else |
| 285 | + { |
| 286 | + parent = doubleRotate(parent,dir); /// align and rotate |
| 287 | + } |
| 288 | + |
| 289 | + parent->color = initcol_parent; /// color will be the same as initial parent |
| 290 | + parent->child[left]->color = BLACK; |
| 291 | + parent->child[right]->color = BLACK; |
| 292 | + |
| 293 | + if(isRedSiblingReduction) |
| 294 | + { |
| 295 | + node->child[dir] = parent; /// fixing the child for proper bottom up fixing later |
| 296 | + } |
| 297 | + else |
| 298 | + { |
| 299 | + node = parent; /// usual black case |
| 300 | + } |
| 301 | + |
| 302 | + ok = true; |
| 303 | + } |
| 304 | + } |
| 305 | + |
| 306 | + return node; |
| 307 | + } |
| 308 | + |
| 309 | + Node* getMax(Node* node) |
| 310 | + { |
| 311 | + Node* now = node; |
| 312 | + |
| 313 | + while (now && now->child[right] != NULL) |
| 314 | + now = now->child[right]; |
| 315 | + |
| 316 | + return now; |
| 317 | + } |
| 318 | +}; |
| 319 | + |
| 320 | +int32_t main() |
| 321 | +{ |
| 322 | +// freopen("input7.txt","r",stdin); |
| 323 | +// freopen("out7.txt","w",stdout); |
| 324 | + |
| 325 | + RBT r; |
| 326 | + |
| 327 | + string option; |
| 328 | + |
| 329 | + while(cin>>option) |
| 330 | + { |
| 331 | + int num; |
| 332 | + cin>>num; |
| 333 | + |
| 334 | + if(option=="F") |
| 335 | + { |
| 336 | + bool has = r.search(num); |
| 337 | + if(has) |
| 338 | + cout<<"True"<<endl; |
| 339 | + else |
| 340 | + cout<<"False"<<endl; |
| 341 | + } |
| 342 | + else if(option=="I") |
| 343 | + { |
| 344 | + r.insert(num); |
| 345 | + r.preorder(); |
| 346 | + } |
| 347 | + else if(option=="D") |
| 348 | + { |
| 349 | + r.delete_(num); |
| 350 | + r.preorder(); |
| 351 | + } |
| 352 | + } |
| 353 | + |
| 354 | + return 0; |
| 355 | +} |
0 commit comments