codeoforces 1101D 树上点分治

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

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

 

题解:

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

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

每次暴力计算即可

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

#include<bits/stdc++.h>
#define endl '\n'
#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;
}

 

posted @ 2019-05-22 09:53  nervending  阅读(193)  评论(0编辑  收藏  举报