Codeforces Round #264 (Div. 2) E. Caisa and Tree
修改操作只有 50 次,最多就只有 $O(50)$ 段查询,每段查询 dfs 一遍统计答案即可。
查询的是一个节点到其根路径上的节点的值,那么就 dfs 进入这个点就把这个点的值加入栈中,离开这个点就把它的值 pop 掉。具体查询方法就是对每种质因子都开一个栈,然后进入一个点就分解它的值,取每种质因子栈顶的节点,取深度最大的节点即可。
#include <bits/stdc++.h> #define pii pair<int, int> const int N = 1e5 + 7; const int W = 2e6 + 7; int prime[N], prin; bool vis[N]; void init() { static const int XN = sqrt(W + 0.5); for (int i = 2; i < XN; i++) { if (!vis[i]) prime[++prin] = i; for (int j = 1; j <= prin && i * prime[j] < XN; j++) { vis[i * prime[j]] = 1; if (i % prime[j] == 0) break; } } } int a[N], head[N], cnt = 1, n, q, ans[N]; struct E { int v, ne; } e[N << 1]; void add(int u, int v) { e[++cnt].v = v; e[cnt].ne = head[u]; head[u] = cnt; e[++cnt].v = u; e[cnt].ne = head[v]; head[v] = cnt; } struct QUERY { int opt, x, y; } que[N]; std::vector<int> vec[W], query[N]; int dep[N]; void dfs1(int u, int f) { dep[u] = dep[f] + 1; for (int i = head[u]; i; i = e[i].ne) { int v = e[i].v; if (v == f) continue; dfs1(v, u); } } int max(int a, int b) { return dep[a] > dep[b] ? a : b; } void dfs(int u, int f) { int w = a[u]; int res = 0; for (int i = 1; i <= prin; i++) { if (w % prime[i] == 0) { if (!vec[prime[i]].empty()) { res = max(vec[prime[i]][vec[prime[i]].size() - 1], res); assert(vec[prime[i]][vec[prime[i]].size() - 1] != u); } vec[prime[i]].push_back(u); while (w % prime[i] == 0) w /= prime[i]; } } if (w > 1) { if (!vec[w].empty()) res = max(vec[w][vec[w].size() - 1], res); vec[w].push_back(u); } for (int id : query[u]) ans[id] = res; for (int i = head[u]; i; i = e[i].ne) { int v = e[i].v; if (v == f) continue; dfs(v, u); } w = a[u]; for (int i = 1; i <= prin; i++) { if (w % prime[i] == 0) { assert(vec[prime[i]][vec[prime[i]].size() - 1] == u); vec[prime[i]].pop_back(); while (w % prime[i] == 0) w /= prime[i]; } } if (w > 1) vec[w].pop_back(); query[u].clear(); } int main() { init(); scanf("%d%d", &n, &q); for (int i = 1; i <= n; i++) scanf("%d", a + i); for (int i = 1, x, y; i < n; i++) { scanf("%d%d", &x, &y); add(x, y); } dfs1(1, 0); int tol = 0; for (int i = 1; i <= q; i++) { scanf("%d%d", &que[i].opt, &que[i].x); if (que[i].opt == 2) scanf("%d", &que[i].y), tol++; ans[i] = -2; } tol = q - tol; for (int i = 1; i <= q; ) { while (i <= q && que[i].opt == 2) { a[que[i].x] = que[i].y; i++; } while (i <= q && que[i].opt == 1) { query[que[i].x].push_back(i); i++; } dfs(1, 0); } for (int i = 1; i <= q; i++) if (ans[i] != -2) printf("%d\n", ans[i] == 0 ? -1 : ans[i]), tol--; assert(tol == 0); return 0; }