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; }