\(\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 加强版的更多相关文章

  1. 「区间DP」「洛谷P1043」数字游戏

    「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...

  2. 洛谷P1120 小木棍 [数据加强版](搜索)

    洛谷P1120 小木棍 [数据加强版] 搜索+剪枝 [剪枝操作]:若某组拼接不成立,且此时 已拼接的长度为0 或 当前已拼接的长度与刚才枚举的长度之和为最终枚举的答案时,则可直接跳出循环.因为此时继续 ...

  3. Solution -「POI 2010」「洛谷 P3511」MOS-Bridges

    \(\mathcal{Description}\)   Link.(洛谷上这翻译真的一言难尽呐.   给定一个 \(n\) 个点 \(m\) 条边的无向图,一条边 \((u,v,a,b)\) 表示从 ...

  4. Solution -「JSOI 2019」「洛谷 P5334」节日庆典

    \(\mathscr{Description}\)   Link.   给定字符串 \(S\),求 \(S\) 的每个前缀的最小表示法起始下标(若有多个,取最小的).   \(|S|\le3\time ...

  5. Solution -「洛谷 P4372」Out of Sorts P

    \(\mathcal{Description}\)   OurOJ & 洛谷 P4372(几乎一致)   设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...

  6. Solution -「APIO 2016」「洛谷 P3643」划艇

    \(\mathcal{Description}\)   Link & 双倍经验.   给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...

  7. 「洛谷4197」「BZOJ3545」peak【线段树合并】

    题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...

  8. 「洛谷3338」「ZJOI2014」力【FFT】

    题目链接 [BZOJ] [洛谷] 题解 首先我们需要对这个式子进行化简,否则对着这么大一坨东西只能暴力... \[F_i=\sum_{j<i} \frac{q_iq_j}{(i-j)^2}-\s ...

  9. 「BZOJ2733」「洛谷3224」「HNOI2012」永无乡【线段树合并】

    题目链接 [洛谷] 题解 很明显是要用线段树合并的. 对于当前的每一个连通块都建立一个权值线段树. 权值线段树处理操作中的\(k\)大的问题. 如果需要合并,那么就线段树暴力合并,时间复杂度是\(nl ...

随机推荐

  1. Cannot uninstall 'pyparsing'. It is a distutils installed project

    我的环境: [root@ansible ~]# python -V Python 2.7.5 [root@ansible ~]# cat /etc/redhat-release CentOS Linu ...

  2. C# 10分钟完成百度翻译(机器翻译)——入门篇

    我们之前基于百度ai开发平台实现了人脸识别 [1].文字识别 [2].语音识别 [3] 与合成的入门和进阶,今天我们来实现百度翻译的实现. 随着"一带一路"政策的开展,各种项目迎接 ...

  3. java下拉框转换公共方法

    1. 下拉框实例类 import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.lang3.Boolean ...

  4. 《剑指offer》面试题57 - II. 和为s的连续正数序列

    问题描述 输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数). 序列内的数字由小到大排列,不同序列按照首个数字从小到大排列. 示例 1: 输入:target ...

  5. leetcode 264. 丑数 II 及 313. 超级丑数

    264. 丑数 II 题目描述 编写一个程序,找出第 n 个丑数. 丑数就是只包含质因数 2, 3, 5 的正整数. 示例: 输入: n = 10 输出: 12 解释: 1, 2, 3, 4, 5, ...

  6. [开发笔记usbTOcan]PyUSB访问设备

    前面的几个章节的介绍,基本把usbTOcan的底层代码设计好,现在需要介绍PC端的PyUSB进行简单的测试. 在文章开始之前,需要简单的介绍一下整个系统. 0 | 部署 这里使用了两块TM4C123G ...

  7. python文档2-unittest单元测试之mock.patch

    介绍mock里面另一种实现方式,patch装饰器的使用,patch() 作为函数装饰器,为您创建模拟并将其传递到装饰函数 patch简介 1.unittest.mock.patch(target,ne ...

  8. gin中multipart/urlencoded表单

    package main import ( "github.com/gin-gonic/gin" ) func main() { router := gin.Default() r ...

  9. IoC容器(底层原理)

    IoC(概念和原理) 1,什么是IoC (1)控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理 (2)使用IoC目的:为了降低耦合度 (3)做入门案例就是IoC实现 2,IoC底层原 ...

  10. Qt中编译器

    很多时候,Qt构建项目编译的过程中会报错,大部分报错是因为qt的设置出现问题,很多时候环境配置时要选择合适的编译器,debugger调试器等,这里对一些名词解释,内容对新手很友好,大佬就不用看啦. M ...