题目大意:给定一棵有根树,边长均为1,对于每一个i,求树上有多少个点对,他们到lca距离的gcd是i。(n<=200,000)

做法:先容斥,求出gcd是i的倍数的点对,考虑长链剖分后从小到大合并计算答案,小的部分先把每个深度的数量变为每个深度的倍数的数量,然后若深度>k,直接到大的里面暴力,若深度<=k,我们在大的里面维护f[i][j]表示深度mod i(1<=i<=k)为j的点数,理论上k取n^0.5时达到最小复杂度O(n^1.5),实际上k比较小的时候常数较小。另外递归计算的时候先递归轻儿子,这样始终都只要存一个f数组。

代码:

#include<cstdio>
inline int read()
{
int x;char c;
while((c=getchar())<''||c>'');
for(x=c-'';(c=getchar())>=''&&c<='';)x=x*+c-'';
return x;
}
#define MN 200000
#define K 20
struct edge{int nx,t;}e[MN+];
int h[MN+],en,d[MN+],ht[MN+],mx[MN+],l[MN+],cnt;
int f[MN+],c[MN+],s[K+][K+];
long long ans[MN+],ss[MN+];
inline void ins(int x,int y){e[++en]=(edge){h[x],y};h[x]=en;}
void dfs(int x)
{
l[x]=++cnt;
if(mx[x])dfs(mx[x]);
for(int i=h[x];i;i=e[i].nx)if(e[i].t!=mx[x])dfs(e[i].t);
}
void solve(int x,int v)
{
for(int i=h[x];i;i=e[i].nx)if(e[i].t!=mx[x])solve(e[i].t,);
if(mx[x])solve(mx[x],);
for(int i=h[x];i;i=e[i].nx)if(e[i].t!=mx[x])
{
for(int j=;j<=ht[e[i].t];++j)
{
c[j]=f[l[e[i].t]+j];
for(int k=j;(k+=j+)<=ht[e[i].t];)f[l[e[i].t]+j]+=f[l[e[i].t]+k];
if(j<K)ans[j+]+=1LL*f[l[e[i].t]+j]*s[j+][d[x]%(j+)];
else for(int k=;(k+=j+)<=ht[x];)ans[j+]+=1LL*f[l[e[i].t]+j]*f[l[x]+k];
}
for(int j=;j<=ht[e[i].t];++j)
{
f[l[x]+j+]+=c[j];
for(int k=;k<=K;++k)s[k][(d[e[i].t]+j)%k]+=c[j];
}
}
f[l[x]]=;
if(v)for(int i=;i<=ht[x];++i)for(int k=;k<=K;++k)s[k][(d[x]+i)%k]-=f[l[x]+i];
else for(int k=;k<=K;++k)++s[k][d[x]%k];
}
int main()
{
int n=read(),i,j;
for(i=;i<=n;++i)++ss[d[i]=d[j=read()]+],ins(j,i);
for(i=n;i;--i)for(j=h[i];j;j=e[j].nx)
if(ht[e[j].t]+>ht[i])ht[i]=ht[mx[i]=e[j].t]+;
dfs();solve(,);
for(i=n;i;--i)for(ss[j=i]+=ss[i+];(j+=i)<=n;)ans[i]-=ans[j];
for(i=;i<n;++i)printf("%lld\n",ans[i]+ss[i]);
}

[UOJ]#33. 【UR #2】树上GCD的更多相关文章

  1. [UOJ UR #2]树上GCD

    来自FallDream的博客,未经允许,请勿转载,谢谢. 传送门 看完题目,一般人都能想到 容斥稳了 .这样我们只要统计有多少点对满足gcd是i的倍数. 考虑长链剖分,每次合并的时候,假设我已经求出轻 ...

  2. 【uoj33】 UR #2—树上GCD

    http://uoj.ac/problem/33 (题目链接) 题意 给出一棵${n}$个节点的有根树,${f_{u,v}=gcd(dis(u,lca(u,v)),dis(v,lca(u,v)))}$ ...

  3. UOJ33 [UR #2] 树上GCD 【点分治】【容斥原理】【分块】

    题目分析: 树上点对问题首先想到点分治.假设我们进行了点分治并递归地解决了子问题.现在我们合并问题. 我们需要找到所有经过当前重心$ c $的子树路径.第一种情况是LCA为当前重心$ c $.考虑以$ ...

  4. 【UOJ#33】【UR#2】树上GCD 有根树点分治 + 容斥原理 + 分块

    #33. [UR #2]树上GCD 有一棵$n$个结点的有根树$T$.结点编号为$1…n$,其中根结点为$1$. 树上每条边的长度为$1$.我们用$d(x,y)$表示结点$x,y$在树上的距离,$LC ...

  5. 【UOJ#33】【UR #2】树上GCD(长链剖分,分块)

    [UOJ#33][UR #2]树上GCD(长链剖分,分块) 题面 UOJ 题解 首先不求恰好,改为求\(i\)的倍数的个数,最后容斥一下就可以解决了. 那么我们考虑枚举一个\(LCA\)位置,在其两棵 ...

  6. UOJ#33. 【UR #2】树上GCD 点分治 莫比乌斯反演

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ33.html 题解 首先我们把问题转化成处理一个数组 ans ,其中 ans[i] 表示 d(u,a) 和 ...

  7. UOJ#33-[UR #2]树上GCD【长链剖分,根号分治】

    正题 题目链接:https://uoj.ac/problem/33 题目大意 给出\(n\)个点的一棵树 定义\(f(x,y)=gcd(\ dis(x,lca),dis(y,lca)\ )\). 对于 ...

  8. 【UR #2】树上GCD

    这道题是有根树点分治+烧脑的容斥+神奇的分块 因为是规定1为根,还要求LCA,所以我们不能像在无根树上那样随便浪了,必须规定父亲,并作特殊讨论 因为gcd并不好求,所以我们用容斥转化一下,求x为gcd ...

  9. uoj33 【UR #2】树上GCD

    题目 大致是长剖+\(\rm dsu\ on\ tree\)的思想 先做一个转化,改为对于\(i\in[1,n-1]\)求出有多少个\(f(u,v)\)满足\(i|f(u,v)\),这样我们最后再做一 ...

随机推荐

  1. web.config中configSections section节 -Z

    由于最近一个项目的数据库变动比较频繁, 为了减少数据层的负担, 打算采用.net的MVC框架, 使用LINQ对付数据层.       这个框架的web.config文件里出现了configSectio ...

  2. loadrunner下载资源时步骤下载超时 (120 seconds) 已过期

    下载资源所用时间超过120秒时,就会报出这个错误,解决方法是设置加大超时时间 运行时设置(快捷键F4) Internet 协议--首选项--高级--选项--General--步骤下载超时(秒) 可以把 ...

  3. 剑指offer-二叉树中和为某一值的路径

    题目描述 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.   解题思路 利用前序遍历的思想,定义FindP ...

  4. HttpWebRequest,HttpWebResponse C# 代码调用webservice,参数为xml

    先上调用代码 public static string PostMoths(string url, string Json) { System.Net.HttpWebRequest request; ...

  5. Leetcode:Two Sum

    原题:https://leetcode.com/problems/two-sum/ 尝试了两种方法: 方法一: var twoSum = function(nums, target) { for(va ...

  6. 2.x与3.x差异、条件语句、数据类型、其他

    一.输入(raw_input)=====>python2.x版本 #!/usr/bin/env python # -*- coding: utf-8 -*- # 将用户输入的内容赋值给 name ...

  7. 实现GridControl的行单元格非顺序跳转

    用GridControl控件添加数据的时候发现,有一些字段过多但是并不是每个字段都需要用户输入,每个单元格都回车跳转的时候不仅浪费时间,而且用户体验也不好,就需要单元格跳转的时候,不需要的字段可以隔过 ...

  8. Python之面向对象四

    面向对象进阶 一.关于面向对象的两个内置函数 isinstance   判断类与对象的关系    isinstance(obj,cls)检查obj是否是类 cls 的对象,返回值是bool值 issu ...

  9. Mysql中autocommit的用法

    定义 Mysql文档原文:SET autocommit disables or enables the default autocommit mode for the current session. ...

  10. 【第二十一篇】手C# MVC 微信授权登录 OAuth2.0授权登录

    首先一定要熟读,最起码过一遍微信开发者文档 微信开发者文档 文档写的很清楚 授权登录四步走 在正文开始前,我得讲清楚一个事情 敲黑板,划重点:微信一共有两个 access_token 一个是7200就 ...