boolisroot(int x){returnls(fa(x)) != x && rs(fa(x)) != x;} voidreverse(int x){swap(ls(x), rs(x)); r(x) ^= 1;} voidspread(int x){ if (r(x)) { if (ls(x)) reverse(ls(x)); if (rs(x)) reverse(rs(x)); r(x) = 0; } }
voidrotate(int x){ int y = fa(x), z = fa(y), c = rs(y) == x, w = ch(x, !c); if (!isroot(y)) ch(z, rs(z) == y) = x; ch(x, !c) = y, ch(y, c) = w; if (w) fa(w) = y; fa(y) = x, fa(x) = z; }
voidsplay(int x){ staticint stc[Maxn], top, y, z; top = 0, y = x, stc[++top] = y; while (!isroot(y)) stc[++top] = y = fa(y); while (top) spread(stc[top--]); while (!isroot(x)) { y = fa(x), z = fa(y); if (!isroot(y)) rotate((rs(y) == x) ^ (rs(z) == y) ? x : y); rotate(x); } }
voidaccess(int x){for (int y = 0; x; x = fa(y = x)) splay(x), rs(x) = y;} voidmakeroot(int x){access(x), splay(x), reverse(x);} intfindroot(int x){ access(x), splay(x); while (ls(x)) spread(ls(x)), x = ls(x); splay(x); return x; }
voidsplit(int x, int y){makeroot(x), access(y), splay(y);} voidlink(int x, int y){makeroot(x); if (findroot(y) != x) fa(x) = y;} voidcut(int x, int y){ makeroot(x); if (findroot(y) != x || fa(y) != x || ls(y)) return; fa(y) = rs(x) = 0; }