zoukankan      html  css  js  c++  java
  • 牛客挑战赛40E 小V和gcd树

    题:https://ac.nowcoder.com/acm/contest/5555/E

    分析:树上路径,带修改,考虑树链剖分,对于操作1,把u的值改为x,影响的权值只是,u的父亲以及他孩子之间的边,那么我们就把重链的部分修改,其他的边不修改,即对u--son[u]和u--fa[u]的边的gcd修改即可(注意后者要保证在当前重链上才可修改);对于操作2,借助tp往上跳的过程中,由于重链上的边我们处理过了,所以这部分直接加,另外就是重链以为的部分边,这些边只可能是u--fa[u]之间的边,所以暴力统计即可

    #include<cstdio>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    using namespace std;
    #define pb push_back
    const int M=2e4+4;
    int fa[M],sz[M],deep[M],ans[M],dfn[M],tp[M],son[M],a[M];
    int cnt;
    vector<int>g[M];
    void dfs1(int u,int f){
        fa[u]=f,sz[u]=1,deep[u]=deep[f]+1;
        for(auto v:g[u]){
            if(v!=f){
                dfs1(v,u);
                sz[u]+=sz[v];
                if(sz[son[u]]<sz[v])
                    son[u]=v;
            }
        }
    }
    void dfs2(int u,int top){
        tp[u]=top;
        dfn[u]=++cnt;
        if(u!=top)
            ans[dfn[u]]=__gcd(a[u],a[fa[u]]);
        if(son[u])
            dfs2(son[u],top);
        for(auto v:g[u]){
            if(v!=fa[u]&&v!=son[u])
                dfs2(v,v);
        }
    }
    int solve(int u,int v,int k){
        int res=0;
        while(tp[u]!=tp[v]){
            if(deep[tp[u]]<deep[tp[v]])
                swap(u,v);
            for(int i=dfn[tp[u]]+1;i<=dfn[u];i++)
                res+=(ans[i]<=k);
            res+=(__gcd(a[tp[u]],a[fa[tp[u]]])<=k);
            u=fa[tp[u]];
        }
        if(deep[u]<deep[v])
            swap(u,v);
        for(int i=dfn[v]+1;i<=dfn[u];i++)
            res+=(ans[i]<=k);
        return res;
    }
    int main(){
        int n,q;
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int u,v,i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            g[u].pb(v),g[v].pb(u);
        }
        dfs1(1,0),dfs2(1,1);
        while(q--){
            int op,u,v,x,k;
            scanf("%d",&op);
            if(op==1){
                scanf("%d%d",&u,&x);
                a[u]=x;
                if(tp[u]!=u)
                    ans[dfn[u]]=__gcd(a[u],a[fa[u]]);
                if(son[u])
                    ans[dfn[son[u]]]=__gcd(a[u],a[son[u]]);
            }
            else{
                scanf("%d%d%d",&u,&v,&k);
                printf("%d
    ",solve(u,v,k));
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Spring学习之旅(二)--容器
    Spring学习之旅(一)--初始Spring
    Logback的使用
    DES加解密工具类
    Lombok插件的使用
    from 表单用 GET 方法进行 URL 传值时后台无法获取问题
    组播
    linux头文件路径
    IANA
    6号板获取或放文件
  • 原文地址:https://www.cnblogs.com/starve/p/12919866.html
Copyright © 2011-2022 走看看