zoukankan      html  css  js  c++  java
  • HDU 6430 TeaTree (线段树合并)

    Problem E. TeaTree

    Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
    Total Submission(s): 1248    Accepted Submission(s): 478


    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.
     
    Input
    On the first line, there is a positive integer n, which describe the number of nodes.
    Next line there are n-1 positive integers f[2] ,f[3], …, f[n], f[i] describe the father of node i on tree.
    Next line there are n positive integers v[2] ,v[3], …, v[n], v[i] describe the value of node i.
    n<=100000, f[i]<i, v[i]<=100000
     
    Output
    Your output should include n lines, for i-th line, output the max number that node i heard.
    For the nodes who heard nothing, output -1.
     
    Sample Input
    4 1 1 3 4 1 6 9
     
    Sample Output
    2 -1 3 -1
     
    Source
     
    思路:
    对每个节点建一棵权值线段树,线段树上插入该点权值的所有的质因数。
     
    更新答案时,我们从底层网上更新,每次将所有的质因数更新到其父节点,同时保留一个最大值。
     
    总体大概就是这样,具体细节需要在敲的时候注意下。
     
    代码如下:
    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+10;
    const int maxm=maxn*400;
    struct node {int u,v,next;}e[maxn];
    int head[maxn],cnt=0;
    inline void add(int u,int v){e[cnt]=node{u,v,head[u]},head[u]=cnt++;}
    vector<int>vec[maxn];
    inline void init(){
        for (int i=1; i<maxn; i++) vec[i].push_back(1);
        for (int i=2; i<maxn; i++){
            vec[i].push_back(i);
            for (int j=i+i; j<maxn; j+=i)
                vec[j].push_back(i);
        }
    }
    int root[maxn],tot,ls[maxm],rs[maxm],sum[maxm];
    inline void pushUp(int rt){
        if(ls[rt] && rs[rt]) sum[rt]=max(sum[ls[rt]],sum[rs[rt]]);
        else if(ls[rt]) sum[rt]=sum[ls[rt]];
        else if(rs[rt]) sum[rt]=sum[rs[rt]];
    }
    void build(int &rt,int l,int r,int pos){
        if(!rt) rt=++tot;
        if(l==r){
            sum[rt]=pos;
            return ;
        }
        int mid=l+r>>1;
        if(pos<=mid) build(ls[rt],l,mid,pos);
        if(pos>mid)  build(rs[rt],mid+1,r,pos);
        pushUp(rt);
    }
    int merge(int rt,int prt,int &ans){
        if(!rt||!prt) return rt^prt;
        if(sum[rt]==sum[prt]) ans=max(ans,sum[rt]);
        if(ls[rt] | ls[prt]) ls[rt]=merge(ls[rt],ls[prt],ans);
        if(rs[rt] | rs[prt]) rs[rt]=merge(rs[rt],rs[prt],ans);
        pushUp(rt);
        return rt;
    }
    int n,ans[maxn];
    void dfs(int u){
        ans[u]=-1;
        for (int i=head[u];~i;i=e[i].next){
            dfs(e[i].v);
            root[u]=merge(root[u],root[e[i].v],ans[u]);
        }
    }
    int main(){
        memset(head,-1,sizeof(head));
        cnt=0,tot=0;
        init();
        scanf("%d",&n);
        for (int fa,i=2; i<=n; i++){
            scanf("%d",&fa);
            add(fa,i);
        }
        for (int x,i=1; i<=n; i++){
            scanf("%d",&x);
            root[i]=0;
            for (int j=0; j<vec[x].size(); j++)
                build(root[i],1,maxn,vec[x][j]);
        }
        dfs(1);
        for (int i=1; i<=n; i++) printf("%d
    ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    万能的everything彻底解决mysql问题
    乱码问题
    机器学习学习规划
    NG机器学习笔记
    书籍与博客
    技术规划
    反置数
    多个接口出现同名函数的处理-转
    接口-imploements-委托
    接口使用中,对象生命周期管理-转
  • 原文地址:https://www.cnblogs.com/acerkoo/p/9539551.html
Copyright © 2011-2022 走看看