版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liufengwei1/article/details/81983239
每个点开个set记录一蛤当前连通块中有哪些因数了,树上dfs下去启发式合并一蛤,一个点的答案必定是两个不同子树中的共同因数,取个大的就行了,3900+ms飘过了233,今天才知道set的clear是可以清空内存的,一开始MLE了,然后vector 清空内存直接swap(e[i],vector<int>())就能内存回收。这题好像有另一种形式,一个序列和另外一个序列任选两个数,然后求最大gcd是多少,也是对每一个数字存所有因数,复杂度nlogn就行了。
#include<bits/stdc++.h>
#define maxl 100010
using namespace std;
int n,cnt;
int fa[maxl],ehead[maxl],val[maxl];
struct ed
{
int to,nxt;
}e[maxl<<1];
vector <int> num[maxl];
set <int> s1[maxl],s2;
set <int> :: iterator it;
int ans[maxl];
inline void add(int u,int v)
{
e[++cnt].to=v;e[cnt].nxt=ehead[u];ehead[u]=cnt;
}
inline void prework()
{
for(int i=1;i<=n;i++)
ehead[i]=0,ans[i]=-1,s1[i].clear();
cnt=0;
for(int i=2;i<=n;i++)
{
scanf("%d",&fa[i]);
add(fa[i],i);
}
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
}
inline int max(int a,int b)
{
if(a>b)return a;
else return b;
}
inline void dfs(int u)
{
int v,szu,szv,l=num[val[u]].size(),d;
for(int i=0;i<l;i++)
s1[u].insert(num[val[u]][i]);
for(int i=ehead[u];i;i=e[i].nxt)
{
v=e[i].to;
dfs(v);
szu=s1[u].size();szv=s1[v].size();
if(szu<szv)
swap(s1[u],s1[v]);
for(it=s1[v].begin();it!=s1[v].end();++it)
{
d=*it;
if(s1[u].count((d)))
ans[u]=max(ans[u],d);
else
s1[u].insert(d);
}
set<int>S;
s1[v].swap(S);
//s1[v].clear();
}
}
inline void mainwork()
{
dfs(1);
}
inline void print()
{
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
}
int main()
{
for(int i=1;i<maxl;++i)
{
int l=sqrt(i);
for(int j=1;j<=l;++j)
if(i%j==0)
{
num[i].push_back(j);
if(j<i/j)
num[i].push_back(i/j);
}
}
while(~scanf("%d",&n))
{
prework();
mainwork();
print();
}
return 0;
}