bitset优化
题意:给一棵树,树上每个节点都有一个权值,问每一个节点任取两个子节点的gcd值最大是多少。解法:
每一个节点设置一个bitset,用来存储节点权值的所有因子,如果因子为x,则在bitset的第x为设置为1。
只要知道每一个子节点存储权值的bitset,就能通过 & 得到共有的因子,而最大的那个因子就是最大的gcd值,合并子节点的bitset可以通过 | 运算符操作,因为bitset有一个函数 _Find_first() 能返回bitset中最低位为1的下标,所以把要存的因子的值x,取反 Maxn-x来存储,通过函数_Find_first()就能快速找出最大的因子是多少。bitset的位运算时间复杂度是log级别的,所以总的时间复杂度是 n\(\times\)\(\sqrt[2]{n}\)\(\times\)\(\log_2{n}\)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <bitset>
#include <cstdlib>
using namespace std;
const int Maxn = 1e5+10;
const int INF = 0x3f3f3f3f;
vector <int> G[Maxn];
int v[Maxn], ans[Maxn];
bitset <Maxn> dfs(int x) {
bitset <Maxn> b1, b2;
for(int i = 1; i*i <= v[x]; ++i) {
if(v[x]%i == 0) b1[Maxn-i] = b1[Maxn-v[x]/i] = 1;
}
int len = G[x].size(), res = -1;
for(int i = 0; i < len; ++i) {
int v = G[x][i];
b2 = dfs(v);
res = max(res, (int)(Maxn-(b1&b2)._Find_first()));
b1 |= b2;
}
ans[x] = res;
return b1;
}
int main(void)
{
int n;
scanf("%d", &n);
int tmp;
for(int i = 2; i <= n; ++i) {
scanf("%d", &tmp);
G[tmp].push_back(i);
}
for(int i = 1; i <= n; ++i) scanf("%d", &v[i]);
dfs(1);
for(int i = 1; i <= n; ++i) printf("%d\n", ans[i]);
return 0;
}
浙公网安备 33010602011771号