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;
 }