vector<int>e[N];
int w[N], dfn[N], subsize[N], fa[N], dep[N], wson[N], top[N];
int tol;
int v[N];
int R[N];
void dfs1(int x, int f) {
subsize[x] = 1;
fa[x] = f;
for (int i = 0; i < e[x].size(); i++) {
int y = e[x][i];
if (y == f)continue;
dep[y] = dep[x] + 1;
dfs1(y, x);
subsize[x] += subsize[y];
if (subsize[y] > subsize[wson[x]])wson[x] = y;
}
}
void dfs2(int x, int t) {
dfn[x] = ++tol;
w[tol] = v[x];
top[x] = t;
if (wson[x])dfs2(wson[x], t);
for (int i = 0; i < e[x].size(); i++) {
int y = e[x][i];
if (y == fa[x] || y == wson[x])continue;
dfs2(y, y);
}
R[x] = tol;
}
struct node {
ll v, lz;
int l, r;
}t[N * 4];
void pushup(int p) {
t[p].v = t[p * 2].v + t[p * 2 + 1].v;
}
void pushdown(int p) {
if (t[p].lz) {
t[p * 2].v += t[p].lz*(t[p * 2].r - t[p * 2].l + 1);
t[p * 2].lz += t[p].lz;
t[p * 2 + 1].v += t[p].lz*(t[p * 2 + 1].r - t[p * 2 + 1].l + 1);
t[p * 2 + 1].lz += t[p].lz;
t[p].lz = 0;
}
}
void build(int l, int r, int p) {
t[p].l = l;
t[p].r = r;
t[p].v = 0;
t[p].lz = 0;
if (l == r) {
t[p].v = w[l];
return;
}
int mid = l + r >> 1;
build(l, mid, p * 2);
build(mid + 1, r, p * 2 + 1);
pushup(p);
}
void update(int L, int R, int v, int p) {
int l = t[p].l, r = t[p].r;
if (L <= l && r <= R) {
t[p].v += v * (r - l + 1);
t[p].lz += v;
return;
}
int mid = l + r >> 1;
pushdown(p);
if (mid >= L)update(L, R, v, p * 2);
if (mid < R)update(L, R, v, p * 2 + 1);
pushup(p);
}
ll query(int L, int R, int p) {
int l = t[p].l, r = t[p].r;
if (L <= l && r <= R) {
return t[p].v;
}
int mid = l + r >> 1;
pushdown(p);
ll sum = 0;
if (mid >= L)sum = (sum + query(L, R, p * 2)) % mod;
if (mid < R)sum = (sum + query(L, R, p * 2 + 1)) % mod;
return sum;
}
struct seg {
int l, r;
}s[N];
int split(int x, int y) {
int cnt = 0;
int fx = top[x], fy = top[y];
while (fx != fy) {
if (dep[fx] < dep[fy]) {
swap(fx, fy);
swap(x, y);
}
s[cnt].l = dfn[fx];
s[cnt++].r = dfn[x];
x = fa[fx];
fx = top[x];
}
if (dfn[x] > dfn[y])swap(x, y);
s[cnt].l = dfn[x], s[cnt++].r = dfn[y];
return cnt;
}
void init(int root, int n) {
tol = 0;
dfs1(root, 0);
dfs2(root, root);
build(1, n, 1);
}
void path_update(int x, int y, int z) {
int n = split(x, y);
for (int i = 0; i < n; i++)
update(s[i].l, s[i].r, z, 1);
}
ll path_query(int x, int y) {
int n = split(x, y);
ll ans = 0;
for (int i = 0; i < n; i++)
ans = (ans + query(s[i].l, s[i].r, 1)) % mod;
return ans;
}
void subtree_update(int x, int z) {
update(dfn[x], R[x], z, 1);
}
ll subtree_query(int x) {
return query(dfn[x], R[x], 1);
}
int lca(int x, int y) {
int fx = top[x], fy = top[y];
while (fx != fy) {
if (dep[fx] < dep[fy]) {
swap(fx, fy);
swap(x, y);
}
x = fa[fx];
fx = top[x];
}
if (dep[x] > dep[y])
return y;
else
return x;
}