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
}
}

执行结果如下:


左神java代码

2021-08-25:给定数组father大小为N,表示一共有N个节点,father[i] = j 表示点i的父亲是点j, father表示的树一定是一棵树而不是森林,queries是二维数组,大小为的更多相关文章

  1. 第3章 Java数组(上): 一维数组和二维数组

    3.数组及排序算法(2天) 3.1 数组的概述 2课时 3.2 一维数组的使用 3课时 3.3 多维数组的使用 3课时 3.4 数组中涉及到的常见算法 3课时 3.5 Arrays工具类的使用 3课时 ...

  2. 数组(Array),二维数组,三维数组

    数组(Array):相同类型数据的集合就叫做数组. (一)定义数组的方法: A) type[] 变量名 = new type[数组中元素的个数] 例如: int[] a = new int[10] ; ...

  3. C Program进阶-二维数组动态内存开辟

    对于二维数组,我们知道可以用Type ArrayName[Row][Colume]的方式来定义,这是一种静态内存开辟的方式,程序在编译的时候就为该数组分配了空间,而且行和列大小也是指定的.这篇文章里我 ...

  4. C/C++怎样传递二维数组,转载自CSDN

    用二维数组作为参数传递(用二维数组处理矩阵),但是希望接受传递二维数组参数的函数可以处理任意维度的数组(希望矩阵的行数和列数都是不固定的). [以下转帖] ---------------------- ...

  5. C#学习笔记04--排序/查找/二维数组/交叉数组

    一. 冒泡排序(重点) 思路:  每次比较把较小的放在前面, 大的放到后面; 图解:下图是最坏情况下的排序 ` 冒泡排序m个元素, 就有(m-1)趟排序, 第一趟m-1次, 第二趟 m-2次....  ...

  6. LeetCode二维数组中的查找

    LeetCode 二维数组中的查找 题目描述 在一个 n*m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增.请完成一个搞笑的函数,输入这样的一个二维数组和一个整数,判断数 ...

  7. 《剑指offer》面试题3:二维数组中的查找

    面试题3:二维数组中的查找 面试题3:二维数组中的查找题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的个二维数组和一个整数,判 ...

  8. LeetCode——Rotate Image(二维数组顺时针旋转90度)

      问题: You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockw ...

  9. php php打乱数组二维数组、多维数组

    php中的shuffle函数只能打乱一维数组,有什么办法快速便捷的打乱多维数组?手册上提供了 <?php function shuffle_assoc($list) {      if (!is ...

  10. Java开发笔记(二十一)二维数组的扩展

    前面介绍的数组容纳的是一串数字,仿佛一根线把这组数字串了起来,故而它只是一维数组.一维数组用来表示简单的数列尚可,要是表达复杂的平面坐标系,那就力不从心了.由于平面坐标系存在水平和垂直两个方向,因此可 ...

随机推荐

  1. IDEA编写JSP无代码提示

    网上的版本 网上的版本 网上的我试了 但是未能解决 我自己解决的方法是 File => Poject Struct=>Modules=>"+"=>找到自己系 ...

  2. Android开发踩坑日记

    ViewModelProviders被弃用,改为ViewModelProvider ViewModelProvider使用方法 MyViewModel model = new ViewModelPro ...

  3. vue中使用vue.extend在dom挂载vue实例

    const CounterComponent = Vue.extend(Counter); this.vm = new CounterComponent({}).$mount('#container' ...

  4. React的行内样式与CSS

    如何为组件添加 CSS 的 class? 传递一个字符串作为 className 属性: render() { return <span className="menu navigat ...

  5. mysql的concat与concat_ws拼接字符串的使用

    concat的使用 可以拼接多个字符 mysql> select concat(name,dept,job) from t1; +-----------------------+ | conca ...

  6. 华为 A800-9000 服务器 离线安装MindX DL 可视化环境+监控

    MindX DL Sample主要应用于企业的数据中心或超算中心机房中,针对不同的应用场景为客户提供AI深度学习端到端解决方案. 传统行业:用户无自建深度学习平台,希望能够提供简单易用.软硬件一体化的 ...

  7. flask-sqlalchemy入门

    Flask-SQLAlchemy 是一个为 Flask 应用增加 SQLAlchemy 支持的扩展.它致力于简化在 Flask 中 SQLAlchemy 的使用.SQLAlchemy 是目前pytho ...

  8. python医学病理图片svs装换

    SVS文件是什么? 最开始拿到SVS文件一脸懵逼的,这货长这样(在windows下可以用Aperio ImageScope这个开源软件打开): 我现在接触的这种图片的大小一般在60M-1.5G之间,可 ...

  9. [数据库/MYSQL]#解决缺陷#设置Unique索引时:"[Err] 1071 - Specified key was too long; max key length is 767 bytes"

    1 问题复现 原表结构: CREATE TABLE `XX_TEMPERATURE` ( `FLOW_ID` int(11) NOT NULL COMMENT '独立的数据表或FTP唯一标识', -- ...

  10. Semantic Kernel 入门系列:🪄LLM的魔法

    ChatGPT 只是LLM 的小试牛刀,让人类能够看到的是机器智能对于语言系统的理解和掌握. 如果只是用来闲聊,而且只不过是将OpenAI的接口封装一下,那么市面上所有的ChatGPT的换皮应用都差不 ...