zoukankan      html  css  js  c++  java
  • [CF1101D] GCD Counting

    Description

    有一颗树,每个点有一个点权,边权都是 (1),问路径上的所有点的 gcd 不是 (1) 的最长路径是多少?

    Solution

    分治到每个点时,考虑当前分治范围内经过该点的路径。

    对于每个子树,记录一个映射,表示每个数能到达的最深的深度,边搜索边更新即可。

    维护当前分治主树的映射,枚举完一个子树后,用子树映射和主树映射中的值更新答案,并将子树映射并入主树映射中。

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    #define foradj(p) for(pair<int,int> pr:g[p])
    #define unpii(q,w) int q=pr.first, w=pr.second;
    const int N = 200005;
    
    vector <pair<int,int> > g[N];
    int dis[N],siz[N],n,m,t1,t2,t3,k[N],vis[N],sum,rt,rtval,val[N],ans;
    vector<int> st,wl;
    set<int> s;
    map<int,int> mp_main,mp_sub;
    
    void findroot(int p,int ff)
    {
        siz[p]=1;
        int mx=0;
        foradj(p)
        {
            unpii(q,w);
            if(!vis[q] && q!=ff)
            {
                findroot(q,p);
                siz[p]+=siz[q];
                mx=max(mx,siz[q]);
            }
        }
        mx=max(mx,sum-siz[p]);
        if(mx<rtval) rtval=mx, rt=p;
    }
    
    void dfs(int p,int ff,int x)
    {
        if(x==1) return;
        mp_sub[x]=max(mp_sub[x],dis[p]);
        foradj(p)
        {
            unpii(q,w);
            if(!vis[q] && q!=ff)
            {
                dis[q]=dis[p]+1;
                dfs(q,p,__gcd(x,val[q]));
            }
        }
    }
    
    void solve(int p)
    {
        vis[p]=1;
        mp_main.clear();
        mp_main[val[p]]=0;
        foradj(p)
        {
            unpii(q,w);
            if(!vis[q])
            {
                dis[q]=1;
                dfs(q,p,__gcd(val[p],val[q]));
                /*cout<<"q="<<q<<" p="<<p<<endl;
                cout<<"sub: ";
                for(auto i:mp_sub) cout<<i.first<<" ";
                cout<<endl;
                cout<<"main:";
                for(auto i:mp_main) cout<<i.first<<" ";
                cout<<endl;*/
                for(auto i:mp_main)
                {
                    for(auto j:mp_sub)
                    {
                        if(__gcd(i.first,j.first)>1)
                        {
                            //cout<<i.first<<" "<<j.first<<endl;
                            ans=max(ans,i.second+j.second+1);
                        }
                    }
                }
                for(auto i:mp_sub)
                {
                    mp_main[i.first]=max(mp_main[i.first],i.second);
                }
                mp_sub.clear();
            }
        }
        foradj(p)
        {
            unpii(q,w);
            if(!vis[q])
            {
                sum=siz[q];
                rtval=1e18;
                findroot(q,0);
                solve(rt);
            }
        }
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>val[i];
        }
        for(int i=1;i<n;i++)
        {
            cin>>t1>>t2;
            g[t1].push_back({t2,1});
            g[t2].push_back({t1,1});
        }
        sum=n;
        rtval=1e18;
        findroot(1,0);
        solve(rt);
        for(int i=1;i<=n;i++) if(val[i]>1) ans=max(ans,1ll);
        cout<<ans<<endl;
    }
    
    
  • 相关阅读:
    Windows 7 SP1无人值守自动应答文件制作
    Ubuntu GNOME单击任务栏图标最小化设置
    NOIP2017题解
    NOIP2017游记
    大模拟1.0
    奇袭
    礼物
    找硬币
    Fiolki
    SQLserver Delete from where 与Oracle delete from where 的差异
  • 原文地址:https://www.cnblogs.com/mollnn/p/13628978.html
Copyright © 2011-2022 走看看