zoukankan      html  css  js  c++  java
  • codeoforces 1101D 树上点分治

    https://codeforces.com/contest/1101/problem/D

    给一个带点权的树,问路上gcd>1的路径长度最大值为多少

    题解:

    树上点分治,维护不可减的树上信息即可

    由于gcd的种类数很低,因此点分治的时候用两个map记录不同gcd的最长路径

    每次暴力计算即可

    需要注意的是,如果所有点权都是1,那么答案应该是0

    #include<bits/stdc++.h>
    #define endl '
    '
    #define ll long long
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mp make_pair
    #define pii pair<int,int>
    #define all(x) x.begin(),x.end()
    #define IO ios::sync_with_stdio(false)
    #define show(x) cout<<#x<<"="<<x<<endl
    #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl
    #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
    #define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
    #define show5(v,w,x,y,z) cout<<#v<<"="<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
    #define showa(a,b) cout<<#a<<'['<<b<<"]="<<a[b]<<endl
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    #define per(ii,a,b) for(int ii=b;ii>=a;--ii)
    #define forn(x,i) for(int i=head[x];i;i=e[i].next)
    using namespace std;
    const int maxn=1e6+10,maxm=2e6+10;
    const int INF=0x3f3f3f3f;
    const int mod=1e9+7;
    const double PI=acos(-1.0);
    int casn,n,m,k;
    int val[maxn];
    class graph{public:
      struct node{int to,next;ll cost;}e[maxm];
      int head[maxn],nume,n,sz[maxn],maxt,stree[maxn];
      void add(int a,int b,ll c=0){e[++nume]={b,head[a],c};head[a]=nume;}
      int vis[maxn],num[maxn],all,mid;
      int dis[maxn],ans;
      map<int,int> cnt1,cnt2;
      void init(int n){
        this->n=n,nume=1,mid=0;
        rep(i,1,n) vis[i]=head[i]=0;
      }
      void getmid(int now=1,int pre=0){
        sz[now]=1;
        for(int i=head[now];i;i=e[i].next){
          if(e[i].to==pre||vis[e[i].to]) continue;
          getmid(e[i].to,now);
          sz[now]+=sz[e[i].to];
        }
        int tmp=max(sz[now]-1,all-sz[now]);
        if(maxt>tmp) maxt=tmp,mid=now;
      }
      void dfs(int now,int pre=0,int gcd=0){
        dis[now]=dis[pre]+1;cnt2[gcd]=max(cnt2[gcd],dis[now]);
        for(int i=head[now];i;i=e[i].next){
          int to=e[i].to;
          if(to==pre||vis[to]) continue;
          dfs(to,now,__gcd(gcd,val[to]));
        }
      }
      void cal(int now){
        cnt1.clear();cnt1[val[now]]=1;dis[now]=1;
        for(int i=head[now];i;i=e[i].next){
          if(vis[e[i].to]) continue;
          int to=e[i].to;
          cnt2.clear();dfs(to,now,__gcd(val[now],val[to]));
          for(auto i:cnt1)
            for(auto j:cnt2){
              int g=__gcd(i.fi,j.fi);
              if(g>1) ans=max(ans,i.se+j.se-1);
            }
          for(auto i:cnt2)
            cnt1[i.fi]=max(i.se,cnt1[i.fi]);
        }
      }
      void getans(int now=1){
        vis[now]=1;cal(now);
        for(int i=head[now];i;i=e[i].next){
          int to=e[i].to;
          if(vis[to]) continue;
          all=sz[to],maxt=n+1;
          getmid(to,now);getans(mid);
        }
      }
      void solve(){
        ans=0;maxt=all=n;
        getmid();getans(mid);
      }
    }g;
    int main() {IO;
      cin>>n;
      g.init(n);
      rep(i,1,n){
        cin>>val[i];
        k=max(val[i],k);
      }
      rep(i,2,n){
        int a,b;cin>>a>>b;
        g.add(a,b);g.add(b,a);
      }
      g.solve();
      if(k>1) g.ans=max(g.ans,1);
      cout<<g.ans<<endl;
    }
    
  • 相关阅读:
    vscode安装插件时报错
    css-flex整理
    java学习之路--String类的基本方法
    java学习之路--面试之并发基础
    java学习之路--面试之多线程基础
    java学习之路--多线程实现的方法
    java学习之路--简单基础的面试题
    java学习之路
    jquery中remove()和empty()是区别
    创建html新元素的三种方法
  • 原文地址:https://www.cnblogs.com/nervendnig/p/10904098.html
Copyright © 2011-2022 走看看