zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    【FZYZOJ】细菌 题解(最短路)
    oracle 开发 第02章 查询
    oracle 开发 第01章 简介
    rhel配置163、epel、rpmforge的yum源
    linux 手动清除缓存
    查看linux内核版本和发行版本
    linux下安装rlwrap
    linux下安装vncserver
    Nagios 安装
    linux mutt发送报表
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12776384.html
Copyright © 2011-2022 走看看