权值线段树合并
线段树维护1~1e5这个值域,对于每个点开一颗线段树,储存值域内最大的因数。
然后对整个树dfs,合并父亲和儿子节点的线段树,在合并过程中更新答案。
#include#define INF 0x3f3f3f3f#define full(a, b) memset(a, b, sizeof a)#define FAST_IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)using namespace std;typedef long long ll;inline int lowbit(int x){ return x & (-x); }inline int read(){ int ret = 0, w = 0; char ch = 0; while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); } while(isdigit(ch)) ret = (ret << 3) + (ret << 1) + (ch ^ 48), ch = getchar(); return w ? -ret : ret;}inline int gcd(int a, int b){ return b ? gcd(b, a % b) : a; }inline int lcm(int a, int b){ return a / gcd(a, b) * b; }template inline T max(T x, T y, T z){ return max(max(x, y), z); }template inline T min(T x, T y, T z){ return min(min(x, y), z); }template inline A fpow(A x, B p, C lyd){ A ans = 1; for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd; return ans;}const int N = 100005;int n, cnt, tot, head[N], w[N], tree[(N*400)<<2], ls[(N*400)<<2], rs[(N*400)<<2], root[N], res[N];struct Edge{ int v, next; }edge[N<<1];vector fac[N];void calc(int x){ if(!fac[x].empty()) return; fac[x].push_back(1), fac[x].push_back(x); for(int i = 2; i <= sqrt(x) + 0.5; i ++){ if(x % i == 0){ fac[x].push_back(i), fac[x].push_back(x / i); } }}int build(){ tot ++; tree[tot] = ls[tot] = rs[tot] = 0; return tot;}void addEdge(int a, int b){ edge[cnt].v = b, edge[cnt].next = head[a], head[a] = cnt ++;}void push_up(int rt){ tree[rt] = max(tree[ls[rt]], tree[rs[rt]]);}void insert(int rt, int l, int r, int val){ if(l == r){ tree[rt] = l; return; } int mid = (l + r) >> 1; if(val <= mid){ if(!ls[rt]) ls[rt] = build(); insert(ls[rt], l, mid, val); } if(val > mid){ if(!rs[rt]) rs[rt] = build(); insert(rs[rt], mid + 1, r, val); } push_up(rt);}int merge(int p, int q, int l, int r, int &ans){ if(!p || !q) return p ^ q; if(tree[p] == tree[q]) ans = max(ans, tree[p]); if(l == r){ tree[p] = max(tree[p], tree[q]); return p; } int mid = (l + r) >> 1; ls[p] = merge(ls[p], ls[q], l, mid, ans); rs[p] = merge(rs[p], rs[q], mid + 1, r, ans); push_up(p); return p;}void dfs(int s, int fa){ res[s] = -1; for(int i = head[s]; i != -1; i = edge[i].next){ int u = edge[i].v; if(u == fa) continue; dfs(u, s); root[s] = merge(root[s], root[u], 1, N, res[s]); }}int main(){ full(head, -1); n = read(); for(int i = 2; i <= n; i ++){ int v = read(); addEdge(v, i), addEdge(i, v); } for(int i = 1; i <= n; i ++) w[i] = read(); for(int i = 1; i <= n; i ++) calc(w[i]); for(int i = 1; i <= n; i ++){ root[i] = build(); for(int j = 0; j < fac[w[i]].size(); j ++){ insert(root[i], 1, N, fac[w[i]][j]); } } dfs(1, 0); for(int i = 1; i <= n; i ++){ printf("%d\n", res[i]); } return 0;}