来自FallDream的博客,未经允许,请勿转载,谢谢。


传送门

看完题目,一般人都能想到 容斥稳了 。这样我们只要统计有多少点对满足gcd是i的倍数。

考虑长链剖分,每次合并的时候,假设我已经求出轻儿子子树内每一个距离的点的数量,我们需要先对这个序列做一个变换,把每个数变成下标是它倍数的数的和。

然后枚举轻儿子到这个点距离dis,这样答案加上现在这棵树内已经计算的部分中 到这个点的距离是dis的倍数的数的和。

考虑分块,对于dis>=k的,暴力做。对于dis<=k的,我们顺便维护数组f[i][j],表示深度膜i等于j的数的数量。

长链剖分的合并次数是O(n)的,所以这个算法的复杂度是根号级别的。

然后玄学调参  我一路调着把块大小从根号那里调到了十几那里巨快  什么鬼 应该是数据问题吧

#include<iostream>
#include<cstdio>
#define MN 200000
#define MK 14
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
struct edge{int to,next;}e[MN+];long long ans[MN+];
int n,head[MN+],cnt=,num[MK+][MK+],fa[MN+],dep[MN+],D[MN+],mxdp[MN+],mx[MN+],s[MN+],S[MN+],*mem[MN+];
inline void ins(int f,int t){e[++cnt]=(edge){t,head[f]};head[f]=cnt;}
void Pre(int x)
{
mxdp[x]=dep[x];mx[x]=;
for(int i=head[x];i;i=e[i].next)
{
Pre(e[i].to);
if(mxdp[e[i].to]>mxdp[x]) mxdp[x]=mxdp[e[i].to],mx[x]=e[i].to;
}
}
void Solve(int x,int flag)
{
for(int i=head[x];i;i=e[i].next)
if(e[i].to!=mx[x]) Solve(e[i].to,);
if(mx[x]) Solve(mx[x],);
for(int i=head[x];i;i=e[i].next)
if(e[i].to!=mx[x])
{
for(int j=dep[e[i].to];j<=mxdp[e[i].to];++j) S[j-dep[e[i].to]+]=mem[e[i].to][j-dep[e[i].to]];
int len=mxdp[e[i].to]-dep[e[i].to]+;
for(int ii=;ii<=len;++ii)
for(int j=ii<<;j<=len;j+=ii) S[ii]+=S[j];
for(int j=;j<=len;++j)
if(j<=MK) ans[j]+=1LL*S[j]*num[j][dep[x]%j];
else for(int k=j;k<=mxdp[x]-dep[x];k+=j) ans[j]+=1LL*S[j]*s[dep[x]+k];
for(int j=dep[e[i].to];j<=mxdp[e[i].to];++j)
{
s[j]+=mem[e[i].to][j-dep[e[i].to]];
for(int k=;k<=MK;++k) num[k][j%k]+=mem[e[i].to][j-dep[e[i].to]];
}
}
++s[dep[x]];for(int j=;j<=MK;++j) ++num[j][dep[x]%j];
if(!flag)
{
mem[x]=new int[mxdp[x]-dep[x]+];
for(int j=dep[x];j<=mxdp[x];++j)
{
mem[x][j-dep[x]]=s[j],s[j]=;
for(int k=;k<=MK;++k) num[k][j%k]=;
}
}
} int main()
{
n=read();
for(int i=;i<=n;++i) ins(fa[i]=read(),i),++D[dep[i]=dep[fa[i]]+];
Pre();Solve(,);
for(int i=n;i;D[i]+=D[i+],--i)
for(int j=i<<;j<=n;j+=i)
ans[i]-=ans[j];
for(int i=;i<n;++i) printf("%lld\n",ans[i]+D[i]);
return ;
}

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

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

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

  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. UOJ#33-[UR #2]树上GCD【长链剖分,根号分治】

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

  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

    题目大意:给定一棵有根树,边长均为1,对于每一个i,求树上有多少个点对,他们到lca距离的gcd是i.(n<=200,000) 做法:先容斥,求出gcd是i的倍数的点对,考虑长链剖分后从小到大合 ...

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

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

  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. 树莓派3启动wifi并且配置wifi

    概述 树莓派3内置了wifi和蓝牙模块,我们不用像以前的版本那样,再去购买一个外接的模块练到raspberry上. 当我们第一次启动了树莓派的时候,必然使用了网线,但是之后的每一次使用,我们当然更希望 ...

  2. HTML标签小记文本类标签

    文本类标签: <input type="text" name="" value="">文本框  type(方式,方法)name文 ...

  3. 为SRS流媒体服务器添加HLS加密功能(附源码)

    为SRS流媒体服务器添加HLS加密功能(附源码) 之前测试使用过nginx的HLS加密功能,会使用到一个叫做nginx-rtmp-module的插件,但此插件很久不更新了,网上搜索到一个中国制造的叫做 ...

  4. 一个诚实的孩纸选Python的原因

    我之所以会选择python语言程序设计这门课,是因为我一开始预选选的选修课都没选上,然后在补选的时候,在别人选剩的课里面选择了python. 上了两节课之后,我发现python还挺有意思的,挺喜欢py ...

  5. Hadoop学习笔记一(HDFS架构)

    介绍 Hadoop分布式文件系统(HDFS)设计的运行环境是商用的硬件系统.他和现存的其他分布式文件系统存在很多相似点.不过HDFS和其他分布式文件系统的区别才是他的最大亮点,HDFS具有高容错的特性 ...

  6. SQL查询语句练习

    最近在学习SQL嘛,所以各个地方找题目来练手,毕竟现在能离得开数据库么? Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(S#,C ...

  7. python之路——初识函数

    阅读目录 为什么要用函数 函数的定义与调用 函数的返回值 函数的参数 本章小结 返回顶部 为什么要用函数 现在python届发生了一个大事件,len方法突然不能直接用了... 然后现在有一个需求,让你 ...

  8. url,href,src之间的区别

    发现自己居然没把url.href.src关系及使用搞清楚,今天就理一下.主要包括:url.src.href定义以及使用区别. URL(Uniform Resource Locator) 统一资源定位符 ...

  9. enumerate给列表加索引

    >>> list = ['a','b','c'] >>> for i,j in enumerate(list): print(i,j) 0 a 1 b 2 c &g ...

  10. Typescript学习

    一 什么是Typescript 简单的说,TypeScript 是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持,它由 Microsoft 开发,代码开源于 GitHub  ...