2021-08-25:给定数组father大小为N,表示一共有N个节点,father[i] = j 表示点i的父亲是点j, father表示的树一定是一棵树而不是森林,queries是二维数组,大小为
2021-08-25:给定数组father大小为N,表示一共有N个节点,father[i] = j 表示点i的父亲是点j, father表示的树一定是一棵树而不是森林,queries是二维数组,大小为M*2,每一个长度为2的数组都表示一条查询,[4,9], 表示想查询4和9之间的最低公共祖先…,[3,7], 表示想查询3和7之间的最低公共祖先…,tree和queries里面的所有值,都一定在0~N-1之间。返回一个数组ans,大小为M,ans[i]表示第i条查询的答案。
福大大 答案2021-08-25:
树链剖分。
代码用golang编写。代码如下:
package main
import "fmt"
func main() {
father := []int{2, 3, 3, 3, 2, 1}
queries := [][]int{
[]int{2, 0},
[]int{0, 4},
[]int{4, 5},
[]int{1, 0},
[]int{2, 2},
}
ret := query3(father, queries)
fmt.Println(ret)
}
// 在线查询最优解 -> 树链剖分
// 空间复杂度O(N), 支持在线查询,单次查询时间复杂度O(logN)
// 如果有M次查询,时间复杂度O(N + M * logN)
func query3(father []int, queries [][]int) []int {
tc := NewTreeChain(father)
M := len(queries)
ans := make([]int, M)
for i := 0; i < M; i++ {
// x y ?
// x x x
if queries[i][0] == queries[i][1] {
ans[i] = queries[i][0]
} else {
ans[i] = tc.lca(queries[i][0], queries[i][1])
}
}
return ans
}
type TreeChain struct {
n int
h int
tree [][]int
fa []int
dep []int
son []int
siz []int
top []int
}
func NewTreeChain(father []int) *TreeChain {
ans := &TreeChain{}
ans.initTree(father)
ans.dfs1(ans.h, 0)
ans.dfs2(ans.h, ans.h)
return ans
}
func (this *TreeChain) initTree(father []int) {
this.n = len(father) + 1
this.tree = make([][]int, this.n)
this.fa = make([]int, this.n)
this.dep = make([]int, this.n)
this.son = make([]int, this.n)
this.siz = make([]int, this.n)
this.top = make([]int, this.n)
this.n--
cnum := make([]int, this.n)
for i := 0; i < this.n; i++ {
if father[i] == i {
this.h = i + 1
} else {
cnum[father[i]]++
}
}
this.tree[0] = make([]int, 0)
for i := 0; i < this.n; i++ {
this.tree[i+1] = make([]int, cnum[i])
}
for i := 0; i < this.n; i++ {
if i+1 != this.h {
cnum[father[i]]--
this.tree[father[i]+1][cnum[father[i]]] = i + 1
}
}
}
func (this *TreeChain) dfs1(u int, f int) {
this.fa[u] = f
this.dep[u] = this.dep[f] + 1
this.siz[u] = 1
maxSize := -1
for _, v := range this.tree[u] {
this.dfs1(v, u)
this.siz[u] += this.siz[v]
if this.siz[v] > maxSize {
maxSize = this.siz[v]
this.son[u] = v
}
}
}
func (this *TreeChain) dfs2(u int, t int) {
this.top[u] = t
if this.son[u] != 0 {
this.dfs2(this.son[u], t)
for _, v := range this.tree[u] {
if v != this.son[u] {
this.dfs2(v, v)
}
}
}
}
func (this *TreeChain) lca(a int, b int) int {
a++
b++
for this.top[a] != this.top[b] {
if this.dep[this.top[a]] > this.dep[this.top[b]] {
a = this.fa[this.top[a]]
} else {
b = this.fa[this.top[b]]
}
}
return twoSelectOne(this.dep[a] < this.dep[b], a, b) - 1
}
func twoSelectOne(c bool, a int, b int) int {
if c {
return a
} else {
return b
}
}
执行结果如下:

2021-08-25:给定数组father大小为N,表示一共有N个节点,father[i] = j 表示点i的父亲是点j, father表示的树一定是一棵树而不是森林,queries是二维数组,大小为的更多相关文章
- 第3章 Java数组(上): 一维数组和二维数组
3.数组及排序算法(2天) 3.1 数组的概述 2课时 3.2 一维数组的使用 3课时 3.3 多维数组的使用 3课时 3.4 数组中涉及到的常见算法 3课时 3.5 Arrays工具类的使用 3课时 ...
- 数组(Array),二维数组,三维数组
数组(Array):相同类型数据的集合就叫做数组. (一)定义数组的方法: A) type[] 变量名 = new type[数组中元素的个数] 例如: int[] a = new int[10] ; ...
- C Program进阶-二维数组动态内存开辟
对于二维数组,我们知道可以用Type ArrayName[Row][Colume]的方式来定义,这是一种静态内存开辟的方式,程序在编译的时候就为该数组分配了空间,而且行和列大小也是指定的.这篇文章里我 ...
- C/C++怎样传递二维数组,转载自CSDN
用二维数组作为参数传递(用二维数组处理矩阵),但是希望接受传递二维数组参数的函数可以处理任意维度的数组(希望矩阵的行数和列数都是不固定的). [以下转帖] ---------------------- ...
- C#学习笔记04--排序/查找/二维数组/交叉数组
一. 冒泡排序(重点) 思路: 每次比较把较小的放在前面, 大的放到后面; 图解:下图是最坏情况下的排序 ` 冒泡排序m个元素, 就有(m-1)趟排序, 第一趟m-1次, 第二趟 m-2次.... ...
- LeetCode二维数组中的查找
LeetCode 二维数组中的查找 题目描述 在一个 n*m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增.请完成一个搞笑的函数,输入这样的一个二维数组和一个整数,判断数 ...
- 《剑指offer》面试题3:二维数组中的查找
面试题3:二维数组中的查找 面试题3:二维数组中的查找题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的个二维数组和一个整数,判 ...
- LeetCode——Rotate Image(二维数组顺时针旋转90度)
问题: You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockw ...
- php php打乱数组二维数组、多维数组
php中的shuffle函数只能打乱一维数组,有什么办法快速便捷的打乱多维数组?手册上提供了 <?php function shuffle_assoc($list) { if (!is ...
- Java开发笔记(二十一)二维数组的扩展
前面介绍的数组容纳的是一串数字,仿佛一根线把这组数字串了起来,故而它只是一维数组.一维数组用来表示简单的数列尚可,要是表达复杂的平面坐标系,那就力不从心了.由于平面坐标系存在水平和垂直两个方向,因此可 ...
随机推荐
- debian 系统中安装 broadcom 无线网卡驱动
首先要修改 apt 的配置文件,允许安装 non-free 软件.即在 /etc/apt/sources.list 中生效的行的最后加上 contrib non-free,再使用 apt-get up ...
- imx6ull调试记录——开发环境搭建
搭建开发环境之网络环境 代码编译环境准备 换源 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak sudo vim /etc/apt/so ...
- 需求分析之道——需求分析要做什么(C系架构设计法,sishuok)
需求分析之道--需求分析要做什么. 需求分析是架构师开始做架构设计的第一步,对架构师来讲非常非常的重要.因为需求分析能够告诉我们,到底我们要做什么,架构设计就是为了去完成这件事情而做的. 接下来,我们 ...
- DSC:数仓SQL脚本迁移的神奇工具
摘要:本文介绍的DSC工具是针对数据库切换时面临的迁移任务而开发的免安装命令行工具.目的是提供简单.快速.可靠的SQL脚本迁移服务. 本文分享自华为云社区<GaussDB(DWS)DSC工具系列 ...
- Redis使用ZSET实现消息队列使用总结一
转载请注明出处: 目录 1.zset为什么可以做消息队列 2.zset实现消息队列的步骤 3.使用jedis实现消息队列示例 4.+inf与-inf 5.redis使用list与zset做消息队列有什 ...
- Qcon 实时音视频专场:实时互动的最佳实践与未来展望
互动直播.线上会议.在线医疗和在线教育是实时音视频技术应用的重要场景,而这些场景对高可用.高可靠.低延时有着苛刻的要求,很多团队在音视频产品开发过程中会遇到各种各样的问题.例如:流畅性,如果在视频过程 ...
- JAVA数据类型以及什么是字节
强类型语言:要求变量的使用要严格符合规定,所有变量都必须先定义才能使用(安全性高) java的数据类型分为两大类 基本类型(primitive type) 引用类型(reference type) / ...
- MySQL日志机制分析
进入正题前先简单看看MySQL的逻辑架构,相信我用的着. MySQL的逻辑架构大致可以分为三层: 第一层:处理客户端连接.授权认证,安全校验等. 第二层:服务器server层,负责对SQL解释.分析. ...
- 图与网络分析—R实现(二)
图与网络 网络在各种实际背景问题中以各种各样的形式存在.交通.电子和通讯网络遍及我们日常生活的各个方面,网络规划也广泛用于解决不同领域中的各种问题,如生产.分配.项目计划.厂址选择.资源管理和财务策划 ...
- pandas这dataframe结构
认识DataFrame结构 DataFrame 一个表格型的数据结构,既有行标签(index),又有列标签(columns),它也被称异构数据表,所谓异构,指的是表格中每列的数据类型可以不同,比如可以 ...