这道E题出奇的简单,直接模拟就行。
先建树,建树的同时记录每个节点的父节点,查询类型为1的时候直接从v的父节点往上找,找到了就直接返回,查询类型为2的时候就直接修改数组的值就好了。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#define M(a,b) memset(a,b,sizeof(a))
#define ll long long
#define rep(i,a,b) for(i=a;i<=b;i++)
using namespace std;
int a[100005],head[100005],e,v;
int fa[100005];
bool vst[100005];
struct E
{
int to,next;
}edge[200005];
inline void addedge(int u,int v)
{
edge[e].to=v;
edge[e].next=head[u];
head[u]=e++;
edge[e].to=u;
edge[e].next=head[v];
head[v]=e++;
}
int gcd(int a,int b)
{
if(!b) return a;
else return gcd(b,a%b);
}
void build_tree(int u)
{
vst[u]=1;
int i,k;
for(i=head[u];i;i=edge[i].next)
{
k=edge[i].to;
if(vst[k]) continue;
fa[k]=u;
build_tree(k);
}
}
int solve(int u)
{
if(!u) return -1;
if(gcd(a[u],a[v])>1) return u;
return solve(fa[u]);
}
int main()
{
int n,q,i,x,y;
e=1;
scanf("%d%d",&n,&q);
rep(i,1,n) scanf("%d",&a[i]);
rep(i,2,n) scanf("%d%d",&x,&y),addedge(x,y);
build_tree(1);
rep(i,1,q)
{
int type;
scanf("%d",&type);
if(type==1)
{
scanf("%d",&v);
printf("%d\n",solve(fa[v]));
}
else
{
int w;
scanf("%d%d",&v,&w);
a[v]=w;
}
}
return 0;
}