Node add(Node t, Node it, int index) { push(t); Node res; if (t == null) res = it; else if (it.prio < t.prio) { Node[] r = split(t, index); it.l = r[0]; it.r = r[1]; res = it; } else { if (index <= cnt(t.l)) t.l = add(t.l, it, index); else t.r = add(t.r, it, index - cnt(t.l) - 1); res = t; } update(res); return res; }
Node remove(Node t, int index) { push(t); Node res; if (index == cnt(t.l)) res = merge(t.l, t.r); else { if (index < cnt(t.l)) t.l = remove(t.l, index); else t.r = remove(t.r, index - cnt(t.l) - 1); res = t; } update(res); return res; }
Node merge(Node l, Node r) { Node res; push(l); push(r); if (l == null) res = r; else if (r == null) res = l; else if (l.prio > r.prio) { l.r = merge(l.r, r); res = l; } else { r.l = merge(l, r.l); res = r; } update(res); return res; }
Node[] split(Node t, int index) { if (t == null) return new Node[2]; push(t); Node[] res; if (index <= cnt(t.l)) { Node[] r = split(t.l, index); t.l = r[1]; res = new Node[] {r[0], t}; } else { Node[] r = split(t.r, index - cnt(t.l) - 1); t.r = r[0]; res = new Node[] {t, r[1]}; } update(t); return res; }