Solution -「POI 2014」「洛谷 P5904」HOT-Hotels 加强版
\(\mathcal{Description}\)
Link.
给定一棵 \(n\) 个点的树,求无序三元组 \((u,v,w)\) 的个数,满足其中任意两点树上距离相等。
\(n\le10^5\)。
\(\mathcal{Solution}\)
考虑如何计数。对于任意三元组 \((u,v,w)\),我们仅在其两两路径所进过的树上最高点对其统计一次。如图:

对于三元组 \((4,6,7)\),我们仅希望在 \(1\) 处统计它的贡献。
考虑 DP,记 \(d(u,v)\) 表示 \(u\) 到 \(v\) 的树上距离。令 \(f(u,i)\) 表示 \(u\) 子树内 \(v\) 的个数,满足 \(d(u,v)=i\);\(g(u,i)\) 表示 \(u\) 子树内无序二元组 \((p,q)\) 的个数,满足 \(d(p,\operatorname{lca}(p,q))=d(q,\operatorname{lca}(p,q))=d(\operatorname{lca}(p,q),u)+i\)。例如上图的 \(g(2,2)=1\),无序二元组 \((4,6)\) 满足条件。
如此设计状态的意义在于,在 \(g(u,i)\) 的基础上,在 \(u\) 子树的外部接上一个满足 \(d(u,w)=i\) 的 \(w\) 就能构成三元组,并且三元组恰好在最高点 \(u\) 计数。
暴力转移比较显然,发现状态的第二维的范围均为 \(u\) 向下的最长链长,所以用长链剖分优化,直接移动指针继承 \(\mathcal O(1)\) 继承长儿子信息,做到均摊 \(\mathcal O(n)\) 转移,故总复杂度 \(\mathcal O(n)\)。
\(\mathcal{Code}\)
#include <cstdio>
#define alloc( u ) \
( f[u] = cur, g[u] = ( cur += dep[u] << 1 ), cur += dep[u] << 1 )
typedef long long LL;
const int MAXN = 1e5;
int n, ecnt, head[MAXN + 5];
int dep[MAXN + 5], son[MAXN + 5];
LL ans, *f[MAXN + 5], *g[MAXN + 5], pool[MAXN * 5], *cur = pool;
struct Edge { int to, nxt; } graph[MAXN * 2 + 5];
inline void link ( const int s, const int t ) {
graph[++ ecnt] = { t, head[s] };
head[s] = ecnt;
}
inline void init ( const int u, const int fa ) {
for ( int i = head[u], v; i; i = graph[i].nxt ) {
if ( ( v = graph[i].to ) ^ fa ) {
init ( v, u );
if ( dep[v] > dep[son[u]] ) son[u] = v;
}
}
dep[u] = dep[son[u]] + 1;
}
inline void solve ( const int u, const int fa ) {
if ( son[u] ) {
f[son[u]] = f[u] + 1, g[son[u]] = g[u] - 1;
solve ( son[u], u );
}
f[u][0] = 1, ans += g[u][0];
for ( int i = head[u], v; i; i = graph[i].nxt ) {
if ( ( v = graph[i].to ) ^ fa && v ^ son[u] ) {
alloc ( v ), solve ( v, u );
for ( int j = 0; j < dep[v]; ++ j ) {
if ( j ) ans += f[u][j - 1] * g[v][j];
ans += g[u][j + 1] * f[v][j];
}
for ( int j = 0; j < dep[v]; ++ j ) {
g[u][j + 1] += f[u][j + 1] * f[v][j];
if ( j ) g[u][j - 1] += g[v][j];
f[u][j + 1] += f[v][j];
}
}
}
}
int main () {
scanf ( "%d", &n );
for ( int i = 1, u, v; i < n; ++ i ) {
scanf ( "%d %d", &u, &v );
link ( u, v ), link ( v, u );
}
init ( 1, 0 );
alloc ( 1 );
solve ( 1, 0 );
printf ( "%lld\n", ans );
return 0;
}
Solution -「POI 2014」「洛谷 P5904」HOT-Hotels 加强版的更多相关文章
- 「区间DP」「洛谷P1043」数字游戏
「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...
- 洛谷P1120 小木棍 [数据加强版](搜索)
洛谷P1120 小木棍 [数据加强版] 搜索+剪枝 [剪枝操作]:若某组拼接不成立,且此时 已拼接的长度为0 或 当前已拼接的长度与刚才枚举的长度之和为最终枚举的答案时,则可直接跳出循环.因为此时继续 ...
- Solution -「POI 2010」「洛谷 P3511」MOS-Bridges
\(\mathcal{Description}\) Link.(洛谷上这翻译真的一言难尽呐. 给定一个 \(n\) 个点 \(m\) 条边的无向图,一条边 \((u,v,a,b)\) 表示从 ...
- Solution -「JSOI 2019」「洛谷 P5334」节日庆典
\(\mathscr{Description}\) Link. 给定字符串 \(S\),求 \(S\) 的每个前缀的最小表示法起始下标(若有多个,取最小的). \(|S|\le3\time ...
- Solution -「洛谷 P4372」Out of Sorts P
\(\mathcal{Description}\) OurOJ & 洛谷 P4372(几乎一致) 设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...
- Solution -「APIO 2016」「洛谷 P3643」划艇
\(\mathcal{Description}\) Link & 双倍经验. 给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...
- 「洛谷4197」「BZOJ3545」peak【线段树合并】
题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...
- 「洛谷3338」「ZJOI2014」力【FFT】
题目链接 [BZOJ] [洛谷] 题解 首先我们需要对这个式子进行化简,否则对着这么大一坨东西只能暴力... \[F_i=\sum_{j<i} \frac{q_iq_j}{(i-j)^2}-\s ...
- 「BZOJ2733」「洛谷3224」「HNOI2012」永无乡【线段树合并】
题目链接 [洛谷] 题解 很明显是要用线段树合并的. 对于当前的每一个连通块都建立一个权值线段树. 权值线段树处理操作中的\(k\)大的问题. 如果需要合并,那么就线段树暴力合并,时间复杂度是\(nl ...
随机推荐
- sqlserver - 查出的结果集,集成为json串放在一个字段里
1.效果 2.sql SELECT top 20 (select [name] as [名字] from staffBasicInfo For JSON PATH,ROOT('第一级key')) k ...
- Oracle 五种约束的创建和移除:
1.主键约束: 创建表的时候就添加: create table table_name (categoryId varchar2(10), categoryName varchar2(30), prim ...
- HIVE执行引擎TEZ学习以及实际使用
概述 最近公司在使用Tez,今天写一篇关于Tez的学习和使用随笔.Tez是Apache最新的支持DAG作业的开源计算框架,它可以将多个有依赖的作业转换为一个作业从而大幅提升DAG作业的性能.Tez并不 ...
- 机器学习&恶意代码静态检测
目录 分析工具 方法概述 二进制灰度图 字节(熵)直方图 字符串信息 ELF结构信息 源码分析与OPcode FCG references: 分析工具 readelf elfparser ninja ...
- 【小问题】为啥乱搞就不行,golang没安装在系统目录下,导致go get出现"package bytes: directory "/home/ahfu/go/src/bytes" is not using a known version control system"
想在自己的账号下安装golang开发环境,于是这样配置: wget https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz cd /home/ahfu ...
- 【测试数据】android下CPU核与线程数的关系
测试方法 24MB的一张4K图片,连续计算5次直方图. 小米mix2s, 高通骁龙 845.4大核,4小核. 数据表格 线程数 绝对时间(s) 累计CPU时间(s) 每线程平均耗时(us) 每线程最大 ...
- 集合框架-ArrayList练习(去除ArrayList集合中的重复元素)
1 package cn.itcast.p3.arraylist.test; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; ...
- python08day
内容回顾 数据类型的补充 str:pass tuple: (1)----->int count 计数 index 通过元组获取索引 list sort 排序从小到大 sort(reverse=T ...
- Protobuf 动态加载 .pb 文件并操作 Message
之前写了<Protobuf 动态加载 .proto 文件并操作 Message>.除了直接读取 .proto 文件之外,还有一种类似的方法.先把 .proto 文件编译成 .pb 文件,再 ...
- C++ 微信多开
应用是如何判断多开 一.通过查找窗口标题或者类名来判断程序是否正在运行. 二.通过互斥对象确定程序是否运行,大多数软件都是使用CreateMutexW 判断多开的. 三.内存映射物理文件,控制多开. ...