HDU6430 Problem E. TeaTree【dsu on tree】

Problem E. TeaTree

Problem Description
Recently, TeaTree acquire new knoledge gcd (Greatest Common Divisor), now she want to test you.
As we know, TeaTree is a tree and her root is node 1, she have n nodes and n-1 edge, for each node i, it has it’s value v[i].
For every two nodes i and j (i is not equal to j), they will tell their Lowest Common Ancestors (LCA) a number : gcd(v[i],v[j]).
For each node, you have to calculate the max number that it heard. some definition:
In graph theory and computer science, the lowest common ancestor (LCA) of two nodes u and v in a tree is the lowest (deepest) node that has both u and v as descendants, where we define each node to be a descendant of itself.

给出一棵以\(1\)为根的树,每个点有权值\(w[i]\),两个不同的点\(u,v\)可以使他们的\(lca\)得到一个大小为\(gcd(w[u],w[v])\)值,现在问每个点所能得到的最大值

可以考虑枚举每个\(lca\),然后任意两个不同的子树中的两个值取\(gcd\),这样是\(n^2\)
考虑启发式合并,用一个数组来记录所有出现过的因子,假设当前处理到点\(u\),现在已经处理出了一些\(u\)的子树中的所有因子了,现在到\(v\)的子树,那就可以先对\(v\)为根的子树中的所有点找出最大出现过的因子,然后再把子树里的所有点的因子加入进去,这样可以防止处理到相同子树中的点

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
int n,w[MAXN],sz[MAXN],son[MAXN],ret[MAXN],res,app[MAXN],st[MAXN],ed[MAXN],id[MAXN],num;
vector<int> d[MAXN],G[MAXN];
void preprocess(){
    for(int i = 1; i < MAXN; i++) for(int j = i; j < MAXN; j+=i) d[j].emplace_back(i);
	for(int i = 1; i < MAXN; i++) reverse(d[i].begin(),d[i].end());
}
void dfs(int u){
    sz[u] = 1; st[u] = ++num; id[num] = u;
    for(int v : G[u]){
        dfs(v);
        sz[u] += sz[v];
        if(sz[v]>sz[son[u]]) son[u] = v;
    }
    ed[u] = num;
}
void update(int val, int inc){ for(int x : d[val]) app[x] += inc; }
int query(int val){ for(int x : d[val]) if(app[x]) return x; return -1; }
void search(int u, bool clear){
    for(int v : G[u]) if(v!=son[u]) search(v,true);
    if(son[u]) search(son[u],false);
    res = -1;
    for(int v : G[u]) if(v!=son[u]) {
        for(int i = st[v]; i <= ed[v]; i++) res = max(res,query(w[id[i]]));
        for(int i = st[v]; i <= ed[v]; i++) update(w[id[i]],1);
    }
    res = max(res,query(w[u]));
    update(w[u],1);
    ret[u] = res;
    if(clear) for(int i = st[u]; i <= ed[u]; i++) update(w[id[i]],-1);
}
void solve(){
    scanf("%d",&n);
    for(int i = 2; i <= n; i++){
        int par; scanf("%d",&par);
        G[par].emplace_back(i);
    }
    for(int i = 1; i <= n; i++) scanf("%d",&w[i]);
    dfs(1);
    search(1,false);
    for(int i = 1; i <= n; i++) printf("%d\n",ret[i]);
}
int main(){
    preprocess();
    solve();
    return 0;
}
posted @ 2020-04-26 00:03  _kiko  阅读(108)  评论(0编辑  收藏  举报