codeforces842C 2000分暴力

题意传送门

题意:

n个节点的树,根节点是1。

每个节点有一个权值,第i个节点权值是 a_i 。

每个节点到根节点的路径上的点的gcd就是该节点的美好值。

想要使该节点的美好值更大,可以使路径上任意一个节点的权值改为0,也可以选择一个不改。

每个节点都相互独立。

数据范围:\dpi{150} 1 \leqslant n \leqslant 2 \cdot 10^5 , 1 \leqslant a_i\leqslant 2\cdot 10^5 。

题解:

每个节点开一个set,记录根节点到当前节点的gcd各种可能以及对应的更改次数,更改此时是0或1。

然后当前节点由父节点转移过来,就是把父节点的set遍历一遍,更改一下,存到当前节点中。

因为因子数并不是很多,所以这样是不会超时的,你意识到这点,这道题就完了。

感受:

看了题解后,一发过。

内心毫无波澜,只觉得自己太弱,没有发现是个暴力。

代码:

#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<int , int> pii ;
const int maxn = 2e5 + 5 ;
int n ;
int a[maxn] ;
int num , head[maxn] ;
int ans[maxn] ;
set<pii> s[maxn] ;
struct Edge
{
	int v , next ;
} edge[maxn << 1] ;
void add_edge(int u , int v)
{
	edge[num].v = v ;
	edge[num].next = head[u] ;
	head[u] = num ++ ;
}
void dfs(int fa , int u)
{
	for(auto x : s[fa])
	{
		if(x.second == 0)
		{
			int y = __gcd(x.first , a[u]) ;
			s[u].insert(make_pair(y , 0)) ;
			ans[u] = max(ans[u] , y) ;
			int z = __gcd(x.first , 0) ;
			s[u].insert(make_pair(z , 1)) ;
			ans[u] = max(ans[u] , z) ;
		}
		else
		{
			int y = __gcd(x.first , a[u]) ;
			s[u].insert(make_pair(y , 1)) ;
			ans[u] = max(ans[u] , y) ;
		}
	}
	for(int i = head[u] ; i != -1 ; i = edge[i].next)
	{
		int v = edge[i].v ;
		if(v == fa)  continue ;
		dfs(u , v) ;
	}
}
int main()
{
	scanf("%d" , &n) ;
	for(int i = 1 ; i <= n ; i ++)  scanf("%d" , &a[i]) ;
	num = 0 , memset(head , -1 , sizeof(head)) ;
	for(int i = 1 ; i <= n - 1 ; i ++)
	{
		int x , y ;
		scanf("%d%d" , &x , &y) ;
		add_edge(x , y) , add_edge(y , x) ;
	}
	memset(ans , 0 , sizeof(ans)) ;
	ans[1] = a[1] ;
	s[1].insert(make_pair(a[1] , 0)) ;
	s[1].insert(make_pair(0, 1)) ;
	for(int i = head[1] ; i != -1 ; i = edge[i].next)
	{
		int v = edge[i].v ;
		dfs(1 , v) ;
	}
	for(int i = 1 ; i <= n ; i ++)  printf("%d " , ans[i]) ;
	printf("\n") ;
	return 0 ;
}
发布了215 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Irving0323/article/details/104123211
今日推荐