This documentation is automatically generated by online-judge-tools/verification-helper
#include "graph/ds/link_cut_tree.hpp"
/*
各 heavy path を head が左, tail が右となるように splay tree で持つ.
ユーザーが直接呼ぶ可能性があるものだけ int でも実装.
LCT 外で探索するときなど,push を忘れないように注意.
*/
template <typename Node>
struct Link_Cut_Tree {
using np = Node *;
int n;
vc<Node> nodes;
Link_Cut_Tree(int n = 0) : n(n), nodes(n) { FOR(i, n) nodes[i] = Node(i); }
Node *operator[](int v) { return &nodes[v]; }
// underlying tree の根
Node *get_root(Node *c) {
expose(c);
c->push();
while (c->l) {
c = c->l;
c->push();
}
splay(c);
return c;
}
// underlying tree の根
int get_root(int c) { return get_root(&nodes[c])->idx; }
// parent(c)==p となるように link. p の根は変わらない.
void link(Node *c, Node *p) {
evert(c);
expose(p);
p->push();
// no edge -> heavy edge
assert(!(c->p));
assert(!(p->r));
c->p = p;
p->r = c;
p->update();
}
// parent(c)==p となるように link. p の根は変わらない.
void link(int c, int p) { return link(&nodes[c], &nodes[p]); }
// a,b が根に変更される
void cut(Node *a, Node *b) {
evert(a);
expose(b);
assert(!b->p);
assert((b->l) == a);
// heavy edge -> no edge
b->l->p = nullptr;
b->l = nullptr;
b->update();
}
// a,b が根に変更される
void cut(int a, int b) { return cut(&nodes[a], &nodes[b]); }
// c を underlying tree の根とする.
// c は splay tree の根にもなる.
// c は push 済になる
void evert(Node *c) {
expose(c);
c->reverse();
c->push();
}
// c を underlying tree の根とする.
// c は splay tree の根にもなる.
void evert(int c) { evert(&nodes[c]); }
// 根は変えない
Node *lca(Node *u, Node *v) {
assert(get_root(u) == get_root(v));
expose(u);
return expose(v);
}
// 根は変えない
int lca(int u, int v) { return lca(&nodes[u], &nodes[v])->idx; }
// 辺の個数. 根を変える.
int dist(int u, int v) {
evert(u), expose(v);
return ((*this)[v]->size) - 1;
}
// 根を変えない.
int depth(int v) {
expose(v);
return ((*this)[v]->size) - 1;
}
// 根を変える.
Node *jump(Node *u, Node *v, int k) {
evert(v);
expose(u);
assert(0 <= k && k < (u->size));
while (1) {
u->push();
int rs = (u->r ? u->r->size : 0);
if (k < rs) {
u = u->r;
continue;
}
if (k == rs) { break; }
k -= rs + 1;
u = u->l;
}
splay(u);
return u;
}
// 根を変える.
int jump(int u, int v, int k) {
auto c = jump((*this)[u], (*this)[v], k);
return c->idx;
}
// [root, c] がひとつの splay tree になるように変更する.
// c が右端で splay tree の根という状態になる.
// path query はこの状態で c の data を見る.
// c は push 済になる
virtual Node *expose(Node *c) {
Node *now = c;
Node *rp = nullptr; // 今まで作ったパス
while (now) {
splay(now);
// heavy -> light, light -> heavy.
if (now->r) { now->add_light(now->r); }
if (rp) { now->erase_light(rp); }
now->r = rp;
now->update();
rp = now;
now = now->p;
}
splay(c);
return rp;
}
// [root, c] がひとつの splay tree になるように変更する.
// c が右端で splay tree の根という状態になる.
// path query はこの状態で c の data を見る.
int expose(int c) {
Node *x = expose(&nodes[c]);
if (!x) return -1;
return x->idx;
}
// 根を変えない.
Node *get_parent(Node *x) {
expose(x);
x->push();
if (!x->l) return nullptr;
x = x->l, x->push();
while (x->r) x = x->r, x->push();
return x;
}
// 根を変えない.
int get_parent(int x) {
Node *p = get_parent((*this)[x]);
return (p ? p->idx : -1);
}
// 根を変える.
void set(Node *c, typename Node::VX x) {
evert(c);
c->set(x);
}
// 根を変える.
void set(int c, typename Node::VX x) { set((*this)[c], x); }
// 根を変える.
typename Node::X prod_path(int a, int b) {
evert(a), expose(b);
return (*this)[b]->x;
}
// 根を変える.
// subtree 用の node を使う
typename Node::X prod_subtree(int v, int root) {
static_assert(Node::NODE_FOR_SUBTREE);
if (v == root) {
evert(root);
return (*this)[root]->x;
}
root = jump(v, root, 1);
cut(v, root);
typename Node::X res = (*this)[v]->x;
link(v, root);
return res;
}
vc<int> collect_heavy_path(int v) {
np c = (*this)[v];
while (!is_root(c)) c = c->p;
vc<int> res;
auto dfs = [&](auto &dfs, np c, bool rev) -> void {
if (!rev) {
if (c->l) dfs(dfs, c->l, rev ^ c->rev);
res.eb(c->idx);
if (c->r) dfs(dfs, c->r, rev ^ c->rev);
} else {
if (c->r) dfs(dfs, c->r, rev ^ c->rev);
res.eb(c->idx);
if (c->l) dfs(dfs, c->l, rev ^ c->rev);
}
};
dfs(dfs, c, false);
return res;
}
void debug() {
print("p, l, r, rev");
auto f = [&](np c) -> int { return (c ? c->idx : -1); };
FOR(i, len(nodes)) { print(i, ",", f((*this)[i]->p), f((*this)[i]->l), f((*this)[i]->r), (*this)[i]->rev); }
FOR(i, len(nodes)) {
np c = (*this)[i];
if (c->l) assert(c->l->p == c);
if (c->r) assert(c->r->p == c);
}
}
void splay(Node *c) {
c->push();
while (!is_root(c)) {
Node *p = c->p;
Node *pp = (p ? p->p : nullptr);
if (state(p) == 0) {
p->push(), c->push();
rotate(c);
}
elif (state(c) == state(p)) {
pp->push(), p->push(), c->push();
rotate(p);
rotate(c);
}
else {
pp->push(), p->push(), c->push();
rotate(c);
rotate(c);
}
}
}
// uv path 上で prod_path(u, x) が check を満たす最後の x, なければ (つまり path(u,u) が ng )-1.
// 根を変える.
// あまり verify されてないよ.
// https://codeforces.com/contest/1039/submission/320681517
// https://codesprintla25.kattis.com/contests/cxeqb3/submissions/17431394
template <class F>
int max_path(F check, int u, int v) {
evert(u), expose(v);
Node *c = (*this)[v];
using MX = typename Node::MX;
using X = typename MX::value_type;
Node *last_ok = nullptr, *last = nullptr;
X lprod = MX::unit();
while (c) {
last = c;
c->push();
X x = (c->l ? MX::op(c->l->x, c->vx) : c->vx);
x = MX::op(lprod, x);
if (!check(x)) {
c = c->l;
} else {
last_ok = c, c = c->r, lprod = x;
}
}
splay(last);
if (!last_ok) return -1;
return last_ok->idx;
}
private:
// splay tree 内で完結する操作. 特に heavy, light 構造は変わらない.
// light pointer は rotate 内でケア
// c は push 済になる
// パスを表す splay tree の根になっているかどうか
// underlying tree ではない
bool is_root(Node *c) { return state(c) == 0; }
// splay tree 内で完結する操作. 特に heavy, light 構造は変わらない.
// light edge のポインタは変更されうる
void rotate(Node *n) {
// n を根に近づける
Node *pp, *p, *c;
p = n->p;
pp = p->p;
if (p->l == n) {
c = n->r;
n->r = p;
p->l = c;
} else {
c = n->l;
n->l = p;
p->r = c;
}
p->update(), n->update();
if (pp) {
if (pp->l == p) pp->l = n;
elif (pp->r == p) pp->r = n;
else {
// light edge pointer が (pp-p) から (pp-n) に変わる
pp->change_light(p, n);
}
}
n->p = pp;
p->p = n;
if (c) c->p = p;
}
inline int state(Node *n) {
if (!n->p) return 0;
if (n->p->l == n) return 1;
if (n->p->r == n) return -1;
return 0;
}
};
#line 1 "graph/ds/link_cut_tree.hpp"
/*
各 heavy path を head が左, tail が右となるように splay tree で持つ.
ユーザーが直接呼ぶ可能性があるものだけ int でも実装.
LCT 外で探索するときなど,push を忘れないように注意.
*/
template <typename Node>
struct Link_Cut_Tree {
using np = Node *;
int n;
vc<Node> nodes;
Link_Cut_Tree(int n = 0) : n(n), nodes(n) { FOR(i, n) nodes[i] = Node(i); }
Node *operator[](int v) { return &nodes[v]; }
// underlying tree の根
Node *get_root(Node *c) {
expose(c);
c->push();
while (c->l) {
c = c->l;
c->push();
}
splay(c);
return c;
}
// underlying tree の根
int get_root(int c) { return get_root(&nodes[c])->idx; }
// parent(c)==p となるように link. p の根は変わらない.
void link(Node *c, Node *p) {
evert(c);
expose(p);
p->push();
// no edge -> heavy edge
assert(!(c->p));
assert(!(p->r));
c->p = p;
p->r = c;
p->update();
}
// parent(c)==p となるように link. p の根は変わらない.
void link(int c, int p) { return link(&nodes[c], &nodes[p]); }
// a,b が根に変更される
void cut(Node *a, Node *b) {
evert(a);
expose(b);
assert(!b->p);
assert((b->l) == a);
// heavy edge -> no edge
b->l->p = nullptr;
b->l = nullptr;
b->update();
}
// a,b が根に変更される
void cut(int a, int b) { return cut(&nodes[a], &nodes[b]); }
// c を underlying tree の根とする.
// c は splay tree の根にもなる.
// c は push 済になる
void evert(Node *c) {
expose(c);
c->reverse();
c->push();
}
// c を underlying tree の根とする.
// c は splay tree の根にもなる.
void evert(int c) { evert(&nodes[c]); }
// 根は変えない
Node *lca(Node *u, Node *v) {
assert(get_root(u) == get_root(v));
expose(u);
return expose(v);
}
// 根は変えない
int lca(int u, int v) { return lca(&nodes[u], &nodes[v])->idx; }
// 辺の個数. 根を変える.
int dist(int u, int v) {
evert(u), expose(v);
return ((*this)[v]->size) - 1;
}
// 根を変えない.
int depth(int v) {
expose(v);
return ((*this)[v]->size) - 1;
}
// 根を変える.
Node *jump(Node *u, Node *v, int k) {
evert(v);
expose(u);
assert(0 <= k && k < (u->size));
while (1) {
u->push();
int rs = (u->r ? u->r->size : 0);
if (k < rs) {
u = u->r;
continue;
}
if (k == rs) { break; }
k -= rs + 1;
u = u->l;
}
splay(u);
return u;
}
// 根を変える.
int jump(int u, int v, int k) {
auto c = jump((*this)[u], (*this)[v], k);
return c->idx;
}
// [root, c] がひとつの splay tree になるように変更する.
// c が右端で splay tree の根という状態になる.
// path query はこの状態で c の data を見る.
// c は push 済になる
virtual Node *expose(Node *c) {
Node *now = c;
Node *rp = nullptr; // 今まで作ったパス
while (now) {
splay(now);
// heavy -> light, light -> heavy.
if (now->r) { now->add_light(now->r); }
if (rp) { now->erase_light(rp); }
now->r = rp;
now->update();
rp = now;
now = now->p;
}
splay(c);
return rp;
}
// [root, c] がひとつの splay tree になるように変更する.
// c が右端で splay tree の根という状態になる.
// path query はこの状態で c の data を見る.
int expose(int c) {
Node *x = expose(&nodes[c]);
if (!x) return -1;
return x->idx;
}
// 根を変えない.
Node *get_parent(Node *x) {
expose(x);
x->push();
if (!x->l) return nullptr;
x = x->l, x->push();
while (x->r) x = x->r, x->push();
return x;
}
// 根を変えない.
int get_parent(int x) {
Node *p = get_parent((*this)[x]);
return (p ? p->idx : -1);
}
// 根を変える.
void set(Node *c, typename Node::VX x) {
evert(c);
c->set(x);
}
// 根を変える.
void set(int c, typename Node::VX x) { set((*this)[c], x); }
// 根を変える.
typename Node::X prod_path(int a, int b) {
evert(a), expose(b);
return (*this)[b]->x;
}
// 根を変える.
// subtree 用の node を使う
typename Node::X prod_subtree(int v, int root) {
static_assert(Node::NODE_FOR_SUBTREE);
if (v == root) {
evert(root);
return (*this)[root]->x;
}
root = jump(v, root, 1);
cut(v, root);
typename Node::X res = (*this)[v]->x;
link(v, root);
return res;
}
vc<int> collect_heavy_path(int v) {
np c = (*this)[v];
while (!is_root(c)) c = c->p;
vc<int> res;
auto dfs = [&](auto &dfs, np c, bool rev) -> void {
if (!rev) {
if (c->l) dfs(dfs, c->l, rev ^ c->rev);
res.eb(c->idx);
if (c->r) dfs(dfs, c->r, rev ^ c->rev);
} else {
if (c->r) dfs(dfs, c->r, rev ^ c->rev);
res.eb(c->idx);
if (c->l) dfs(dfs, c->l, rev ^ c->rev);
}
};
dfs(dfs, c, false);
return res;
}
void debug() {
print("p, l, r, rev");
auto f = [&](np c) -> int { return (c ? c->idx : -1); };
FOR(i, len(nodes)) { print(i, ",", f((*this)[i]->p), f((*this)[i]->l), f((*this)[i]->r), (*this)[i]->rev); }
FOR(i, len(nodes)) {
np c = (*this)[i];
if (c->l) assert(c->l->p == c);
if (c->r) assert(c->r->p == c);
}
}
void splay(Node *c) {
c->push();
while (!is_root(c)) {
Node *p = c->p;
Node *pp = (p ? p->p : nullptr);
if (state(p) == 0) {
p->push(), c->push();
rotate(c);
}
elif (state(c) == state(p)) {
pp->push(), p->push(), c->push();
rotate(p);
rotate(c);
}
else {
pp->push(), p->push(), c->push();
rotate(c);
rotate(c);
}
}
}
// uv path 上で prod_path(u, x) が check を満たす最後の x, なければ (つまり path(u,u) が ng )-1.
// 根を変える.
// あまり verify されてないよ.
// https://codeforces.com/contest/1039/submission/320681517
// https://codesprintla25.kattis.com/contests/cxeqb3/submissions/17431394
template <class F>
int max_path(F check, int u, int v) {
evert(u), expose(v);
Node *c = (*this)[v];
using MX = typename Node::MX;
using X = typename MX::value_type;
Node *last_ok = nullptr, *last = nullptr;
X lprod = MX::unit();
while (c) {
last = c;
c->push();
X x = (c->l ? MX::op(c->l->x, c->vx) : c->vx);
x = MX::op(lprod, x);
if (!check(x)) {
c = c->l;
} else {
last_ok = c, c = c->r, lprod = x;
}
}
splay(last);
if (!last_ok) return -1;
return last_ok->idx;
}
private:
// splay tree 内で完結する操作. 特に heavy, light 構造は変わらない.
// light pointer は rotate 内でケア
// c は push 済になる
// パスを表す splay tree の根になっているかどうか
// underlying tree ではない
bool is_root(Node *c) { return state(c) == 0; }
// splay tree 内で完結する操作. 特に heavy, light 構造は変わらない.
// light edge のポインタは変更されうる
void rotate(Node *n) {
// n を根に近づける
Node *pp, *p, *c;
p = n->p;
pp = p->p;
if (p->l == n) {
c = n->r;
n->r = p;
p->l = c;
} else {
c = n->l;
n->l = p;
p->r = c;
}
p->update(), n->update();
if (pp) {
if (pp->l == p) pp->l = n;
elif (pp->r == p) pp->r = n;
else {
// light edge pointer が (pp-p) から (pp-n) に変わる
pp->change_light(p, n);
}
}
n->p = pp;
p->p = n;
if (c) c->p = p;
}
inline int state(Node *n) {
if (!n->p) return 0;
if (n->p->l == n) return 1;
if (n->p->r == n) return -1;
return 0;
}
};