hdu 6430 Teatree
给定一棵n个点的有根树,1为根节点,每个点有一个点权。询问每个点的子树下任意两个数字的gcd最大是多少。
我们可以先把1e5以内所有数字的因数求出来。因为1e5以内数字的因数不超过200个。所以可以暴力做些事情。
树上启发式合并,将重儿子的所有节点的权值以及权值的因子保存下来,然后依次合并轻儿子。
当一个权值第一次出现时,将他所有的因子数量+1。将轻儿子依次合并之前,先看是否有因子出现过,有的话答案更新,然后在合并。
删除的时候当一个数字出现次数为0时,将他的因子数量-1。
#include <bits/stdc++.h> using namespace std; const int M = 1e5+7; int head[M],cnt,n,V[M]; vector<int> vec[M],s; int sz[M],son[M],ans[M],vis[M],num[M]; struct edge{ int v,next; }e[M<<1]; void add(int u,int v){ e[++cnt].v=v;e[cnt].next=head[u]; head[u]=cnt; } void dfs(int u,int fa){ sz[u]=1; son[u]=-1; for(int i=head[u];~i;i=e[i].next){ int v=e[i].v; if(v==fa) continue; dfs(v,u); sz[u]+=sz[v]; if(son[u]==-1||sz[v]>sz[son[u]]) son[u]=v; } return ; } void add_node(int u){ num[V[u]]++; if(num[V[u]]==1){ for(int i=0;i<vec[V[u]].size();i++){ vis[vec[V[u]][i]]++; } } } void del_node(int u){ num[V[u]]--; if(num[V[u]]==0){ for(int i=0;i<vec[V[u]].size();i++){ vis[vec[V[u]][i]]--; } } } void del_tree(int u,int fa){ del_node(u); for(int i=head[u];~i;i=e[i].next){ int v=e[i].v; if(v==fa) continue; del_tree(v,u); } } void add_tree(int u,int fa){ s.push_back(u); for(int i=head[u];~i;i=e[i].next){ int v=e[i].v; if(v==fa) continue; add_tree(v,u); } } void dfs1(int u,int fa){ if(sz[u]==1){ add_node(u); return ; } for(int i=head[u];~i;i=e[i].next){ int v=e[i].v; if(v==fa||v==son[u]) continue; dfs1(v,u); del_tree(v,u); } dfs1(son[u],u); int tmp=-1; for(int i=head[u];~i;i=e[i].next){ s.clear(); int v=e[i].v; if(v==fa||v==son[u]) continue; add_tree(v,u); for(int j=0;j<s.size();j++){ for(int k=0;k<vec[V[s[j]]].size();k++){ if(vis[vec[V[s[j]]][k]]) ans[u]=max(ans[u],vec[V[s[j]]][k]); } } for(int j=0;j<s.size();j++) add_node(s[j]); } for(int i=0;i<vec[V[u]].size();i++){ if(vis[vec[V[u]][i]]) ans[u]=max(ans[u],vec[V[u]][i]); } add_node(u); } int main(){ for(int i=1;i<=100005;i++){ for(int j=1;j*i<=100005;j++){ vec[i*j].push_back(i); } } scanf("%d",&n); cnt=0;memset(head,-1,sizeof(head)); for(int i=2;i<=n;i++){ int u; scanf("%d",&u); add(u,i); } for(int i=1;i<=n;i++){ scanf("%d",&V[i]); ans[i]=-1; } dfs(1,-1);//找重儿子 dfs1(1,-1); for(int i=1;i<=n;i++) printf("%d\n",ans[i]); return 0; }