[UOJ]#33. 【UR #2】树上GCD
题目大意:给定一棵有根树,边长均为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的更多相关文章
- [UOJ UR #2]树上GCD
来自FallDream的博客,未经允许,请勿转载,谢谢. 传送门 看完题目,一般人都能想到 容斥稳了 .这样我们只要统计有多少点对满足gcd是i的倍数. 考虑长链剖分,每次合并的时候,假设我已经求出轻 ...
- 【uoj33】 UR #2—树上GCD
http://uoj.ac/problem/33 (题目链接) 题意 给出一棵${n}$个节点的有根树,${f_{u,v}=gcd(dis(u,lca(u,v)),dis(v,lca(u,v)))}$ ...
- UOJ33 [UR #2] 树上GCD 【点分治】【容斥原理】【分块】
题目分析: 树上点对问题首先想到点分治.假设我们进行了点分治并递归地解决了子问题.现在我们合并问题. 我们需要找到所有经过当前重心$ c $的子树路径.第一种情况是LCA为当前重心$ c $.考虑以$ ...
- 【UOJ#33】【UR#2】树上GCD 有根树点分治 + 容斥原理 + 分块
#33. [UR #2]树上GCD 有一棵$n$个结点的有根树$T$.结点编号为$1…n$,其中根结点为$1$. 树上每条边的长度为$1$.我们用$d(x,y)$表示结点$x,y$在树上的距离,$LC ...
- 【UOJ#33】【UR #2】树上GCD(长链剖分,分块)
[UOJ#33][UR #2]树上GCD(长链剖分,分块) 题面 UOJ 题解 首先不求恰好,改为求\(i\)的倍数的个数,最后容斥一下就可以解决了. 那么我们考虑枚举一个\(LCA\)位置,在其两棵 ...
- UOJ#33. 【UR #2】树上GCD 点分治 莫比乌斯反演
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ33.html 题解 首先我们把问题转化成处理一个数组 ans ,其中 ans[i] 表示 d(u,a) 和 ...
- UOJ#33-[UR #2]树上GCD【长链剖分,根号分治】
正题 题目链接:https://uoj.ac/problem/33 题目大意 给出\(n\)个点的一棵树 定义\(f(x,y)=gcd(\ dis(x,lca),dis(y,lca)\ )\). 对于 ...
- 【UR #2】树上GCD
这道题是有根树点分治+烧脑的容斥+神奇的分块 因为是规定1为根,还要求LCA,所以我们不能像在无根树上那样随便浪了,必须规定父亲,并作特殊讨论 因为gcd并不好求,所以我们用容斥转化一下,求x为gcd ...
- uoj33 【UR #2】树上GCD
题目 大致是长剖+\(\rm dsu\ on\ tree\)的思想 先做一个转化,改为对于\(i\in[1,n-1]\)求出有多少个\(f(u,v)\)满足\(i|f(u,v)\),这样我们最后再做一 ...
随机推荐
- Beta冲刺第四天
一.昨天的困难 没有困难. 二.今天进度 1.林洋洋:修复协作详情,日程详情日程类型显示纠正 2.黄腾达:修复管理者查看协作成员可以移除自己的问题,加入登录.注册表单按回车键就可直接完成操作的功能 3 ...
- Alpha冲刺No.4
冲刺Day4 一.站立式会议 本来还想今天下午好好弄弄安卓开发,结果计划赶不上变化.(不存在的) 完成备忘录设计,个人界面设计 二.实际项目进展 搞了404(安卓和ssm的连接),好像还是不太行. 备 ...
- 百词斩APP分析
一.调研 1.第一次上手 第一次使用,可以使用微信和qq登录感觉挺不错的不然又要注册有点麻烦,在功能上,用户可以针对自身选择不同水平的英语背单词,然后有多钟方式对自己的听力和单词翻译进行提升.在u ...
- 去掉xcode编译warning:ld: warning: directory not found for option '-L
选择工程, 编译的 (targets) 选择 Build Settings 菜单 查找 Library Search Paths 和 Framework Search Paths, 删掉编译报warn ...
- JAVA中最容易让人忽视的基础。
可能很多找编程工作的人在面试的时候都有这种感受,去到一个公司填写面试试题的时候,多数人往往死在比较基础的知识点上.不要奇怪,事实就是如此一般来说,大多数公司给出的基础题大概有122道,代码题19道左右 ...
- IOS webview iframe 宽度超出屏幕解决方案
IOS 真机webview中,iframe 却不能很好地适应屏幕大小,总是超出屏幕尺寸,需要左右滚动才能看到完整页面. <div style="overflow: auto;-webk ...
- Hangfire使用ApplicationInsigts监控
起因 我司目前使用清真的ApplicationInsights(以下简称Ai)来做程序级监控.(Ai相关文档: https://azure.microsoft.com/zh-cn/services/a ...
- angular2 学习笔记 ( app initialize 初始化 )
refer : http://stackoverflow.com/questions/39033835/angularjs2-preload-server-configuration-before-t ...
- 关于tomcat和jetty的乱码问题
现象:windows 下的tomcat和jetty默认安装都有问题,linux下的没有问题. 分析:操作系统字符集发生作用了,程序有些处理可能使用了该默认字符集,导致两边现象不一致,建议排查,先尝试通 ...
- (java基础)Java输入输出流及文件相关
字节流: 所有的字节输入输出都继承自InputStream和OutputStream,通常用于读取二进制数据,最基本单位为单个字节,如图像和声音.默认不使用缓冲区. FileInputStream和F ...