题目大意:给定一棵有根树,边长均为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. Beta No.6

    今天遇到的困难: github服务器响应很慢 推图的API接口相应较慢,超过了初始设定的最大延迟时间,导致了无法正确返回图片 ListView滑动删除Demo出现了某些Bug,这些Bug可能导致了某些 ...

  2. Beta 第六天

    今天遇到的困难: github服务器响应很慢 推图的API接口相应较慢,超过了初始设定的最大延迟时间,导致了无法正确返回图片 ListView滑动删除Demo出现了某些Bug,这些Bug可能导致了某些 ...

  3. Beta 第二天

    今天遇到的困难: 组员对github极度的不适应 Android Studio版本不一致项目难以打开运行 移植云端的时候,愚蠢的把所有项目开发环境全部搬上去.本身云的内存小,性能差,我们花费了太多时间 ...

  4. 20162330 第10周 MySort实验

    关于MySort的进一步实践 课堂作业题目如下: 模拟实现Linux下Sort -t : -k 2的功能.参考Sort的实现.提交码云链接和代码运行截图. import java.util.*; pu ...

  5. 201621123062《Java程序设计》第一周学习总结

    1.本周学习总结 关键词: 初步熟悉Java的基本组成.语言特点(简单性.结构中立性).运行环境.简单语法等. 关键概念之间的联系: 1.JVM是Java程序唯一认识的操作系统,其可执行文件为.cla ...

  6. Beta冲刺Day6

    项目进展 李明皇 今天解决的进度 进行前后端联动调试 明天安排 完善程序运行逻辑 林翔 今天解决的进度 服务器端发布消息,删除消息,检索消息,个人发布的action 明天安排 图片功能遇到问题,微信小 ...

  7. NOIP2012 提高组 Day 2

    http://www.cogs.pro/cogs/page/page.php?aid=16 期望得分:100+100+0=0 实际得分:100+20+0=120 T2线段树标记下传出错 T1 同余方程 ...

  8. bzoj千题计划245:bzoj1095: [ZJOI2007]Hide 捉迷藏

    http://www.lydsy.com/JudgeOnline/problem.php?id=1095 查询最远点对,带修改 显然可以用动态点分治 对于每个点,维护两个堆 堆q1[x] 维护 点分树 ...

  9. python识别验证码——PIL,pytesser,pytesseract的安装

    1.使用Python识别验证码需要安装Python的图像处理模块(PIL.pytesser.pytesseract) (安装过程需要pip,在我的Python中已经安装pip了,pip的安装就不在赘述 ...

  10. C# 使用 GDI+ 画图

    最近做一个微信公众号服务,有一些简单的图片处理功能.主要就是用户在页面操作,前端做一些立刻显示的效果,然后提交保存时后端真正修改原图. 我们的后端是 ASP.NET,也就是 C# 语言了,C# 本身处 ...