题目大意:维护一个可查询、修改的树,查询的是一个节点的:离它距离最近的、组成两个节点Key值的质因数存在交集的、祖先节点;修改是修改一个节点的key值。
如果组成两个Key值的质因数存在交集,则两个数的最大公因数大于 1.查询时,一个节点一个节点往树根找满足该条件的节点即可。
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX_NODE = 100010;
struct Node
{
int Key, Id;
Node *Father;
}_nodes[MAX_NODE];
void Init(int n)
{
for (int i = 1; i <= n; i++)
_nodes[i].Id = i;
}
void Build(int faId, int sonId)
{
Node *fa = _nodes + faId, *son = _nodes + sonId;
son->Father = fa;
}
void Update(int uId, int val)
{
_nodes[uId].Key = val;
}
int Gcd(int a, int b)
{
return b ? Gcd(b, a%b) : a;
}
int Query(int uId)
{
Node *cur = _nodes + uId;
for (Node *older = cur->Father; older; older = older->Father)
if (Gcd(cur->Key, older->Key) > 1)
return older->Id;
return -1;
}
int main()
{
int n, opCnt, key, op, u, fa, son, val;
scanf("%d%d", &n, &opCnt);
Init(n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &key);
Update(i, key);
}
for (int i = 1; i <= n - 1; i++)
{
scanf("%d%d", &fa, &son);
Build(fa, son);
}
while (opCnt--)
{
scanf("%d%d", &op, &u);
switch (op)
{
case 1:
printf("%d\n", Query(u));
break;
case 2:
scanf("%d", &val);
Update(u, val);
break;
}
}
return 0;
}