codeforces 990G 点分治

https://codeforces.com/contest/990/problem/G

2e5以内,能够形成的gcd非常有限,一条链内至多也就是log2e5个,

因此可以暴力点分治+子树合并,虽然复杂度比线性做法多了一个log,但是不怎么费脑子

复杂度大约是$100*nlogn$,

其实还有很多优化空间,比如gcd为1就跳出dfs_dis之类的

#include
#include
#include
#define ll long long
#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(i,x,g,e) for(int i=g[x];i;i=e[i].next)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ull unsigned long long
#define fi first
#define se second
#define mp make_pair
#define pii pair
#define all(x) x.begin(),x.end()
#define show(x) cout<<#x<<"="<g[maxn];
  int all,sz[maxn],root,maxt;
  bool vis[maxn];
  int dfs_root(int now,int fa){
    int cnt=1;
    for(auto to:g[now]){
      if(to==fa||vis[to])continue;
      cnt+=dfs_root(to,now);
    }
    int tmp=max(cnt-1,all-cnt);
    if(maxt>tmp) maxt=tmp,root=now;
    return sz[now]=cnt;
  }//@基础部分@
  ll ans[maxn];
  int dis[maxn],dfn,cnt[maxn],gcd[maxn],tot;
  void dfs_dis(int now,int fa,int d){
    dis[++dfn]=d;
    for(auto to:g[now]){
      if(to==fa||vis[to]) continue;
      dfs_dis(to,now,__gcd(d,val[to]));
    }
  }
  void cal(int now){
    tot=1;
    gcd[1]=val[now];
    cnt[val[now]]=1;
    for(auto to:g[now]){
      if(vis[to]) continue;
      dfn=0;
      dfs_dis(to,now,__gcd(val[now],val[to]));
      rep(i,1,dfn){
        int x=dis[i];
        rep(j,1,tot)ans[__gcd(gcd[j],x)]+=cnt[gcd[j]];
      }
      rep(i,1,dfn){
        if(!cnt[dis[i]]) gcd[++tot]=dis[i];
        cnt[dis[i]]++;
      }
    }
    rep(i,1,tot) cnt[gcd[i]]=0;
    ans[val[now]]++;
  }
  void dfs_dv(int now){
    vis[now]=1;
    cal(now);
    for(auto to:g[now]){
      if(vis[to]) continue;
      all=sz[to],maxt=1e9,root=n+1;
      dfs_root(to,now);
      dfs_dv(root);
    }
  }
  void solve(int n){
    all=n,maxt=1e9;
    dfs_root(1,1);
    dfs_dv(root);
  }
} 
using namespace graph;
int main() {IO;
  cin>>n;
  rep(i,1,n) cin>>val[i];
  rep(i,2,n){
    int a,b;cin>>a>>b;
    g[a].push_back(b);
    g[b].push_back(a);
  }
  solve(n);
  rep(i,1,2e5){
    if(ans[i]) cout<

 

转载于:https://www.cnblogs.com/nervendnig/p/11623284.html

你可能感兴趣的:(codeforces 990G 点分治)