• HDU6430 Problem E. TeaTree【dsu on tree】


    Problem E. TeaTree

    Problem Description
    Recently, TeaTree acquire new knoledge gcd (Greatest Common Divisor), now she want to test you.
    As we know, TeaTree is a tree and her root is node 1, she have n nodes and n-1 edge, for each node i, it has it’s value v[i].
    For every two nodes i and j (i is not equal to j), they will tell their Lowest Common Ancestors (LCA) a number : gcd(v[i],v[j]).
    For each node, you have to calculate the max number that it heard. some definition:
    In graph theory and computer science, the lowest common ancestor (LCA) of two nodes u and v in a tree is the lowest (deepest) node that has both u and v as descendants, where we define each node to be a descendant of itself.

    给出一棵以(1)为根的树,每个点有权值(w[i]),两个不同的点(u,v)可以使他们的(lca)得到一个大小为(gcd(w[u],w[v]))值,现在问每个点所能得到的最大值

    可以考虑枚举每个(lca),然后任意两个不同的子树中的两个值取(gcd),这样是(n^2)
    考虑启发式合并,用一个数组来记录所有出现过的因子,假设当前处理到点(u),现在已经处理出了一些(u)的子树中的所有因子了,现在到(v)的子树,那就可以先对(v)为根的子树中的所有点找出最大出现过的因子,然后再把子树里的所有点的因子加入进去,这样可以防止处理到相同子树中的点

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1e5+7;
    int n,w[MAXN],sz[MAXN],son[MAXN],ret[MAXN],res,app[MAXN],st[MAXN],ed[MAXN],id[MAXN],num;
    vector<int> d[MAXN],G[MAXN];
    void preprocess(){
        for(int i = 1; i < MAXN; i++) for(int j = i; j < MAXN; j+=i) d[j].emplace_back(i);
    	for(int i = 1; i < MAXN; i++) reverse(d[i].begin(),d[i].end());
    }
    void dfs(int u){
        sz[u] = 1; st[u] = ++num; id[num] = u;
        for(int v : G[u]){
            dfs(v);
            sz[u] += sz[v];
            if(sz[v]>sz[son[u]]) son[u] = v;
        }
        ed[u] = num;
    }
    void update(int val, int inc){ for(int x : d[val]) app[x] += inc; }
    int query(int val){ for(int x : d[val]) if(app[x]) return x; return -1; }
    void search(int u, bool clear){
        for(int v : G[u]) if(v!=son[u]) search(v,true);
        if(son[u]) search(son[u],false);
        res = -1;
        for(int v : G[u]) if(v!=son[u]) {
            for(int i = st[v]; i <= ed[v]; i++) res = max(res,query(w[id[i]]));
            for(int i = st[v]; i <= ed[v]; i++) update(w[id[i]],1);
        }
        res = max(res,query(w[u]));
        update(w[u],1);
        ret[u] = res;
        if(clear) for(int i = st[u]; i <= ed[u]; i++) update(w[id[i]],-1);
    }
    void solve(){
        scanf("%d",&n);
        for(int i = 2; i <= n; i++){
            int par; scanf("%d",&par);
            G[par].emplace_back(i);
        }
        for(int i = 1; i <= n; i++) scanf("%d",&w[i]);
        dfs(1);
        search(1,false);
        for(int i = 1; i <= n; i++) printf("%d
    ",ret[i]);
    }
    int main(){
        preprocess();
        solve();
        return 0;
    }
    
  • 相关阅读:
    WCF系列之双工通信 牧羊人
    WCF系列之承载(IISHTTP) 牧羊人
    在Ubuntu 10.10下安装JDK配置Eclipse及Tomcat【转载 + 订正】
    gconfeditor简介【转载】
    Ubuntu10.10(linux) 安装jdk1.6及环境变量的设置【转载】
    ubuntu下txt文件中文显示乱码的方法【转载】
    程序员的编辑器——VIM【转载】
    xx is not in the sudoers file 问题解决【转载】
    win7下配置PHP+apache+mysql【转载 + 补充】
    ubuntu忘记密码,忘记root密码的解决方法!【转载】
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12776384.html
Copyright © 2020-2023  润新知