【树论 倍增】51nod1709 复杂度分析
倍增与位运算有很多共性;这题做法有一点像「线段树上二分」和「线段树套二分」的关系。
Input
第一行一个数n表示点数(1<=n<=100,000)
接下来n-1行每行两个数x,y表示一条边(1<=x,y<=n)
Output
一个数表示答案
Input示例
4
1 2
1 3
2 4
Output示例
8
题目分析
题目已经良心地把要求的式子给出来了。
自上向下的方法一
位运算计数题自然而然考虑按位计算贡献,注意到要求的是bit即个数,也就是说高位和低位是同性的。而这题略有特殊的是在于可以与倍增相结合做一些有趣的事情。
由于边权为1,倍增预处理的到祖先节点的二的幂次,就是到祖先节点的距离的二进制拆分。
那么就可以先枚举logn数量的每一种2^i深度d,再枚举所有n个点。对于每一个枚举的点,统计与它相距2^{d-1}<dis≤2^d的祖先节点的贡献。

直观来说就是这张图。主要代码是这样的:
for (int d=; d<; d++)
{
memset(w, , sizeof w);
for (int ix=; ix<=n; ix++)
{
int i = chain[ix]; //树的dfs序,因为要自上向下做
w[i] = tot[f[i][d+]]-tot[f[i][d]];
if (dep[i] > <<(d+)) w[i] += w[fa[f[i][d+]]];
ans += w[i];
}
}
如果想要更加程式化的描述,见51Nod1709 复杂度分析这篇博客。
#include<bits/stdc++.h>
const int maxn = ; int n,w[maxn];
long long ans;
int chain[maxn],tot[maxn],chTot;
int f[maxn][],dep[maxn],fa[maxn];
int edgeTot,edges[maxn<<],nxt[maxn<<],head[maxn]; int read()
{
char ch = getchar();
int num = ;
bool fl = ;
for (; !isdigit(ch); ch = getchar())
if (ch=='-') fl = ;
for (; isdigit(ch); ch = getchar())
num = (num<<)+(num<<)+ch-;
if (fl) num = -num;
return num;
}
void addedge(int u, int v)
{
edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
edges[++edgeTot] = u, nxt[edgeTot] = head[v], head[v] = edgeTot;
}
void dfs(int x, int fat)
{
f[x][] = x, f[x][] = fa[x] = fat, dep[x] = dep[fat]+;
tot[x] = , chain[++chTot] = x;
for (int i=head[x]; i!=-; i=nxt[i])
{
int v = edges[i];
if (v!=fat){
dfs(v, x);
tot[x] += tot[v];
}
}
}
int main()
{
memset(head, -, sizeof head);
n = read();
for (int i=; i<n; i++) addedge(read(), read());
dfs(, );
for (int j=; j<=; j++)
for (int i=; i<=n; i++)
f[i][j] = fa[f[f[i][j-]][j-]];
for (int d=; d<; d++)
{
memset(w, , sizeof w);
for (int ix=; ix<=n; ix++)
{
int i = chain[ix];
w[i] = tot[f[i][d+]]-tot[f[i][d]];
if (dep[i] > <<(d+)) w[i] += w[fa[f[i][d+]]];
ans += w[i];
}
}
printf("%lld\n",ans);
return ;
}
自上向下的方法二
在这里给出一种O(nlog)的做法。记录每个节点的fa和子树size。
枚举一个k,用s[i]表示节点i子树内和i距离小于 2^k 大于等于2^k−1的节点数,v[i]表示节点i子树内和i距离小于 2^k 大于等于 2^k−1 的节点和i距离的bit总数,now[i]表示i向上的第 2^k−1 个祖先。
每次倍增计算每个点子树内和它距离小于 2^k 大于等于 2^k−1 的点的距离对答案的贡献即可。@hzq84621 自http://www.51nod.com/question/index.html#!questionId=1546
【博客园抽风没法正常显示数学公式我也很难受啊】
END
【树论 倍增】51nod1709 复杂度分析的更多相关文章
- [51nod1709]复杂度分析
给出一棵n个点的树(以1号点为根),定义dep[i]为点i到根路径上点的个数.众所周知,树上最近公共祖先问题可以用倍增算法解决.现在我们需要算出这个算法精确的复杂度.我们定义计算点i和点j最近公共组先 ...
- 51nod1709复杂度分析
题解: 注意到,如果第j位有贡献,那么从i往上跳2^j,然后不能再跳超过2^j. 因此可以考虑倍增. 代码: #include<bits/stdc++.h> typedef long lo ...
- CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先)
CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先) 题意分析 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天, ...
- 数据结构( Pyhon 语言描述 ) — — 第3章:搜索、排序和复杂度分析
评估算法的性能 评价标准 正确性 可读性和易维护性 运行时间性能 空间性能(内存) 度量算法的运行时间 示例 """ Print the running times fo ...
- bzoj5089 最大连续子段和 分块+复杂度分析+凸包
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5089 题解 本来打算迟一点再写这个题解的,还有一个小问题没有弄清楚. 不过先写一下存个档吧. ...
- [HNOI2016]树(可持久化线段树+树上倍增)
[HNOI2016]树(可持久化线段树+树上倍增) 题面 给出一棵n个点的模板树和大树,根为1,初始的时候大树和模板树相同.接下来操作m次,每次从模板树里取出一棵子树,把它作为新树里节点y的儿子.操作 ...
- 51nod 1709 复杂度分析
51nod 1709 复杂度分析 考虑定义 $ F(x) $ 为 \(x\) 为根的子树所有点与 $ x $ 的深度差(其实就是 $ x $ 到每个子树内点的距离)的 1 的个数和. 注意,$ F(x ...
- 分布式机器学习:同步并行SGD算法的实现与复杂度分析(PySpark)
1 分布式机器学习概述 大规模机器学习训练常面临计算量大.训练数据大(单机存不下).模型规模大的问题,对此分布式机器学习是一个很好的解决方案. 1)对于计算量大的问题,分布式多机并行运算可以基本解决. ...
- 相似度分析,循环读入文件(加入了HanLP,算法第四版的库)
相似度分析的,其中的分词可以采用HanLP即可: http://www.open-open.com/lib/view/open1421978002609.htm /****************** ...
随机推荐
- 快速删除node_modules文件夹
前言 当安装了较多模块后,node_modules目录下的文件会很多,直接删除整个目录会很慢,下面介绍些快速删除node_modules目录的方法. 方法一:使用rimraf模块的命令 在全局安装ri ...
- python操作redis之hash操作
# __author__ = 'STEVEN' import redis,time #连接池 polls = redis.ConnectionPool(host='192.168.43.22',por ...
- 《http和https协议》
一.HTTP协议 1.官方概念: HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文 ...
- __getitem__,__setitem__,__delitem__
__getitem__.__setitem__.__delitem__ 总结: __getitem__,__setitem_,__delitem__ : obj[‘属性’]的方式去操作属性时触发的方法 ...
- 洛谷 P1042 乒乓球
P1042 乒乓球 var s:string; a1:array[1..50000] of char; i,n,x,y:longint; procedure f1; begin while not e ...
- MySQL之select简单使用
Select * from table_name Select column_name_1,column_name_2 from table_name Select * from student wh ...
- C#中MessageBox用法大全(附效果图)<转>
我们在程序中经常会用到MessageBox. MessageBox.Show()共有21中重载方法.现将其常见用法总结如下: 1.MessageBox.Show("Hello~~~~&quo ...
- IIS+PHP访问量大时内存爆满等性能问题解决方案
如今还是有许多人在用老掉牙的 IIS6 + PHP.本文解决方法适用于使用 FastCGI 运行 PHP 的用户. 问题原因: 你可以试一试,你在 VPS 上用 IIS6 安装 FastCGI 跑 P ...
- gin 打linux环境包问题解决
打window包直接go build一下,完事, 但是,打linux包出现如下错误 ..\github.com\mattn\go-isatty\isatty_linux.go:7:8: cannot ...
- 关于js对象中的,属性的增删改查问题
删除主要是delet方法: 1 function Person(){}; 2 var person = new Person(); 3 person.name = 'yy'; 4 person.gen ...