forn(q,Q) { char op[8]; scanf("%s", op); if (op[0] == 'I') { int x,y; scanf("%d%d", &x,&y); x--; // Esto es parecido (pero bien diferente :P) al codigo de insertarAUnladoPointer, pero empezando en p en lugar de en root // De entrada me comi que era hacer lo mismo exacto que insertarAUnLado, y pegue WA. // Y luego me comi otro WA por olvidarme la linea p = p->h(0); :P // Moraleja: esto seria bastante mas error prone que el split obvio. Nodo<Datos> *p = iesimo(x, t), *nodo = new Nodo<Datos>(y); int lado = 0; if (p->h(0)) { p = p->h(0); lado = 1; while (p->h(1)) p = p->h(1); } p->hang(lado, nodo); nodo->flotar(); t.reroot(); } else if (op[0] == 'D') { int x; scanf("%d", &x); x--; t.erasePointer(iesimo(x, t)); } else if (op[0] == 'R') { int x,y; scanf("%d%d", &x, &y); x--; Nodo<Datos> *p = iesimo(x, t); p->dat.x = y; p->fullUpdate(); } else if (op[0] == 'Q') { int x,y; scanf("%d%d", &x,&y); x--; assert(x < y); Treap<Datos> t2,t3; t.splitPointer(iesimo(x, t), t2); t2.splitPointer(iesimo(y-x, t2), t3); printf("%d\n", t2.root->dat.bestSum); t.merge(t2); t.merge(t3); } else assert(false); }
Nodo<Datos> *iesimo(int i, Treap<Datos> &t) { Nodo<Datos> *p = t.root; while (true) { assert(p); int L = tam(p->h(0)); if (i < L) p = p->h(0); else if (i == L) return p; else { i -= L + 1; p = p->h(1); } } }