luogu2441 角色属性树

题目大意:维护一个可查询、修改的树,查询的是一个节点的:离它距离最近的、组成两个节点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;
}

  

原文地址:https://www.cnblogs.com/headboy2002/p/8934001.html