[HDU 6430] 2018 Multi-University Training Contest 10 Problem E. TeaTree 暴力 bitset

题目链接:Problem E. TeaTree

题目大意

一颗树, 每个节点上有一个小于等于1e5的数字, 然后每个节点的值等于所有以它为LCA 的节点对(i, j)中gcd(v[i], v[j])的最大值, 要求输出所有节点的值

思路

一开始想到用bitset记录每个节点的所有因数, 但TLE了, 没想到G++的bitset有一个函数叫做_Find_first()能玄学地快速找到为1的最低位, 赛后改用这个函数就AC了
具体思路是后序遍历这棵树, 这样可以保证访问某节点时, 它的所有子节点都已经访问过了, 然后每个节点用一个bitset记录它和它的所有子节点所有因子(要预处理[1, 1e5]所有数字的所有因子)
一开始将节点的bitset设置为本结点v[i]的因子情况, 然后以当前节点为LCA的节点对, 要么是一个为本节点, 一个为其子节点, 要么两个来自其不同的两个子节点, 两个bitset相与就能得到其所有公因子, 取最大的一个就是答案
因为每次只需要用的当前节点和其直接子节点的bitset, 当我们处理完当前节点后, 将其所有子节点的bitset删除, 否则会TLE
要求最大的公因子(即bitset最高的1位置), _Find_first(), 只能找到最低位为1的位置, 所以一开始就将bitset反过来就好了

代码

Accepted 6430 1107MS 18604K 1633 B G++

#include 
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100, mod = 1e9 + 7, sqrn = 320;
int n;
struct edge
{
    int from, to, nxt;
};
edge es[maxn];
int head[maxn];

vector<int> divisor[maxn];
inline void addedge(int id, int from, int to)
{
    es[id].from = from;
    es[id].to = to;
    es[id].nxt = head[from];
    head[from] = id;
}
bitset *bitv[maxn];
int f[maxn], v[maxn];
int ans[maxn];

void dfs(int u)
{
    for(int i=head[u]; i; i=es[i].nxt)
    {
        int v=es[i].to;
        dfs(v);
    }
    bitv[u] = new bitset(0);
    for(auto &ite : divisor[v[u]])
    {
        (*bitv[u])[maxn-1-ite] = 1;
    }
    int x;
    for(int i=head[u]; i; i=es[i].nxt)
    {
        int v = es[i].to;
        x = ((*bitv[u]) & (*bitv[v]))._Find_first();
        if(x1-x, ans[u]);
        (*bitv[u]) |= (*bitv[v]);
    }

    for(int i=head[u]; i; i=es[i].nxt)
    {
        int v = es[i].to;
        delete bitv[v];
    }
}

int main()
{
    for (int i = 1; i < maxn; ++i)
    {
        for (int j = i; j < maxn; j += i) divisor[j].push_back(i);
    }    
    scanf("%d", &n);
    for(int i=2; i<=n; ++i) scanf("%d", f+i);
    for(int i=1; i<=n; ++i) scanf("%d", v+i);
    for(int i=2; i<=n; ++i) 
    {
        addedge(i, f[i], i);
    }
    dfs(1);
    for(int i=1; i<=n; ++i) 
    {
        if(ans[i] == 0) printf("-1\n");
        else printf("%d\n", ans[i]);
    }

    return 0;
}

你可能感兴趣的:(bitset)