题目大意:维护一个可查询、修改的树,查询的是一个节点的:离它距离最近的、组成两个节点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 ", Query(u)); break; case 2: scanf("%d", &val); Update(u, val); break; } } return 0; }