UOJ#33-[UR #2]树上GCD【长链剖分,根号分治】
正题
题目链接:https://uoj.ac/problem/33
题目大意
给出nnn个点的一棵树
定义f(x,y)=gcd(dis(x,lca),dis(y,lca))f(x,y)=gcd(\ dis(x,lca),dis(y,lca)\ )f(x,y)=gcd( dis(x,lca),dis(y,lca) )。
对于每个iii求有多少对f(x,y)=i(x<y)f(x,y)=i(x<y)f(x,y)=i(x<y)
1≤n≤1051\leq n\leq 10^51≤n≤105
解题思路
首先肯定是枚举lcalcalca节点,然后看他子树里的情况,比较麻烦的是gcdgcdgcd刚刚好是ddd,但是其实我们可以是ddd的倍数的情况,然后后面再容斥出答案。
如果,然后暴力算的话首先需要一个长链剖分,然后每次是lenloglenlen\ log\ lenlen log len的。
但是仔细想一想就会发现这个复杂度其实是假的,因为每次暴力算的话的lenlenlen是这条链上面那条链的lenlenlen。
考虑点其他做法,因为是枚举倍数,我们可以上我们的根号分治
对于dis>ndis>\sqrt ndis>n的情况,我们之间暴力枚举倍数,因为这样不会超过n\sqrt nn次
对于dis≤ndis\leq \sqrt ndis≤n的情况,我们考虑储存一些东西,设gi,jg_{i,j}gi,j表示当前的链中depdepdep模iii为jjj的点的个数,然后处理的时候我们就可以直接用这个来计算了。
这样平衡下来时间复杂度就是O(nn)O(n\sqrt n)O(nn)了
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cctype>
using namespace std;
const int N=2e5+10;
struct node{int to,next;
}a[N];
int n,T,len[N],dep[N],h[N],g[400][400];
int tot,t[N],ls[N],son[N],*f[N],*now;
long long ans[N],pre[N];
int read(){int x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
void addl(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;
}
void dfs(int x){for(int i=ls[x];i;i=a[i].next){int y=a[i].to;dep[y]=dep[x]+1;dfs(y);if(len[y]>len[son[x]])son[x]=y;}len[x]=len[son[x]]+1;return;
}
void calc(int x,int top){f[x][0]=1;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==son[x])continue;f[y]=now;now+=len[y];calc(y,y);}if(son[x]){f[son[x]]=f[x]+1;calc(son[x],top);}for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==son[x])continue;for(int j=1;j<=len[y];j++)t[j]=f[y][j-1];for(int j=1;j<=len[y];j++)for(int k=2*j;k<=len[y];k+=j)t[j]+=t[k];for(int j=1;j<=len[y];j++)if(j>T){for(int k=j;k<len[x];k+=j)ans[j]+=1ll*f[x][k]*t[j];}else ans[j]+=1ll*g[j][dep[x]%j]*t[j];for(int j=1;j<=len[y];j++)f[x][j]+=f[y][j-1];for(int j=0;j<len[y];j++)for(int k=1;k<=T;k++)g[k][(j+dep[y])%k]+=f[y][j];}for(int i=1;i<=T;i++)g[i][dep[x]%i]++;if(x==top){for(int i=1;i<=T;i++)for(int j=0;j<len[x];j++)g[i][(j+dep[x])%i]=0;}return;
}
signed main()
{n=read();for(int i=2;i<=n;i++)addl(read(),i);dfs(1);T=sqrt(n);if(T>350)T=350;f[1]=now=h;now+=len[1];calc(1,1);for(int i=n;i>=1;i--)for(int j=2*i;j<=n;j+=i)ans[i]-=ans[j];for(int i=2;i<=n;i++)pre[dep[i]]++;for(int i=n;i>=1;i--)pre[i]+=pre[i+1];for(int i=1;i<n;i++)printf("%lld\n",ans[i]+pre[i]);return 0;
}
UOJ#33-[UR #2]树上GCD【长链剖分,根号分治】相关推荐
- 【UOJ#33】【UR #2】树上GCD(长链剖分/根号分类讨论)
[UOJ#33][UR #2]树上GCD 求解树上两个点到lca的距离的最大公约数是k的对数 首先我们很容易就想到莫比乌斯反演,那么利用倍数形式,我们只需要求解是i的倍数的对数. 考虑枚举lca,这个 ...
- UOJ#284-快乐游戏鸡【长链剖分,线段树】
正题 题目链接:https://uoj.ac/problem/284 题目大意 nnn个点的一棵树,每个点有一个wiw_iwi表示至少死亡wiw_iwi次才能通过这个点,否则就会死亡.只能往子节点 ...
- Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)
题面 Bzoj 洛谷 题解 首先把最短路径树建出来(用\(Dijkstra\),没试过\(SPFA\)\(\leftarrow\)它死了),然后问题就变成了一个关于深度的问题,可以用长链剖分做,所以我 ...
- UOJ284 快乐游戏鸡(树上动态规划问题、长链剖分+单调栈)
Description 一棵 n 个点的有根树,带点权 wi. 从 s 出发,希望达到 t,每秒可以从当前点移动到某一个儿子. 有一个死亡次数,初始为 0.若在某个点 i(i != s, t) 时,死 ...
- hdu 4607 Park Visit(树上最长链)
求树上最长链:两遍搜索. 第一次从树上任意点开始,最远点必然是某一条最长链上的端点u. 第二次从u开始,最远点即该最长链的另一端点. 先在最长链上走,不足再去走支链. 把询问数m错打成n,狠狠wa了一 ...
- [树上最长链][tarjan][单调队列][环上前缀和] Jzoj P5905 黑暗之魂(darksoul)
Description oi_juruo热爱一款名叫黑暗之魂的游戏.在这个游戏中玩家要操纵一名有 点生命值的无火的余灰在一张地图中探险.地图中有n个篝火(也就是存档点).在篝火处休息可以将生命值恢复满 ...
- 1577 例题3 数字转换(LOJ10155) 约数计算 树上最长链(两次找最大深度)
总目录 在线测评地址(ybt) 在线测评地址(LOJ) 发现竟然读不懂题.努力静下来,再读题,总算有了眉目. 4→3→1→74的约数,不包括本身,1,2,约数和是1+2=3, 3的约数,不包括本身,1 ...
- 【luogu P5903】【模板】树上 k 级祖先(长链剖分)
[模板]树上 k 级祖先 题目链接:luogu P5903 题目大意 给你一棵树,要你在线 O(1) 求一个点的 k 级祖先. 思路 这个我们可以用长链剖分来做,从而可以做到预处理 O ( n log ...
- 对LCA、树上倍增、树链剖分(重链剖分长链剖分)和LCT(Link-Cut Tree)的学习
LCA what is LCA & what can LCA do LCA(Lowest Common Ancestors),即最近公共祖先 在一棵树上,两个节点的深度最浅的公共祖先就是 L ...
最新文章
- Ubuntu 12.04安装Sun JDK 6
- 小P寻宝记——好基友一起走 背包
- ios证书导出不了p12文件_IOS苹果证书无法生成.P12文件解决方法
- python有道翻译接口-【Python】Python利用有道翻译开发API应用示例
- 再说 Spring AOP
- sqlserver查看跟某个表相关的所有存储过程
- java 打包下载文件_java下载打包下载文件
- 产品铭牌要求_AMPULM:电力变压器铭牌有哪些主要技术参数,你都知道吗?
- FreeModbus移植到STM32F103(串行传输方式)
- 蒙特卡洛方法_程序媛转TA之理论篇十三:蒙特卡洛方法
- 干货!286页李宏毅《深度学习讲义》
- 2021年下半年网络工程师上午真题及答案解析
- 转]Linux杀死进程方法大全
- [Ceoi2010]Pin
- ssis for循环容器_SSIS包中的序列容器
- 在windows server 2003服务器上提供NTP时间同步服务
- 【GEE】配置本地python环境
- vsftpd配置详解
- 二阶微分方程解法总结 Summary of Second Order Equations
- 映美精LoadDeviceStateFromFile问题
热门文章
- matlab作业1参考答案,matlab课后习题答案1到6章
- aggregation java_Elasticsearch Aggregation 多个字段分组统计 Java API实现
- linux ll 转数组,List、Set、数组之间的转换
- d.ts文件可以注释html吗,如何编写一个d.ts文件的步骤详解_旧店_前端开发者
- html站点如何命名,html页面的CSS、DIV命名规则
- mysql 8 配置参数优化_mysql8 参考手册--配置非持久性优化器统计参数
- idea怎么把代码放到git_在IDEA中如何初始化Git,把项目推送到Git上
- 78. 子集022(回溯法)
- C++ 学习之旅(10)——static与extern
- 「offer来了」2种递进学习思维,24道计网题目,保姆级巩固你的计网知识体系