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. 在app中如何使weib-view不铺满全屏,自适应页面

    // #ifdef APP-PLUS //自建webview var currentWebview = this.$scope.$getAppWebview(); var height = this. ...

  2. uglifyjs-webpack-plugin配置

    项目使用vuecli3搭建,在vue.config.js文件中进行配置,主要配置了去除线上环境的打印信息. 首先安装插件, 执行命令 npm install uglifyjs-webpack-plug ...

  3. windows2012通过powershell安装远程组件技巧

    概要: 通过服务器管理器安装远程桌面服务会报错一直没有办法解决 之后了解到安装组件可以通过powershell命令安装   powershell命令说明 https://docs.microsoft. ...

  4. DRF_基本使用

    基本使用 视图内 from rest_framework.viewsets import ModelViewSet from app01 import models from app01 import ...

  5. oracle学习笔记1 安装 虚拟机 plsql 连接 oracle

    第一步就是安装 为了节省资源,运行起来更快捷,首先是在电脑上安装好vm虚拟机, 新建虚拟机,安装xp,也就是把xp光盘文件导入, 接着在虚拟机中下载oracle,解压的话会用到WinRAR,也一并导入 ...

  6. ElasticSearch 实现分词全文检索 - 高亮查询

    目录 ElasticSearch 实现分词全文检索 - 概述 ElasticSearch 实现分词全文检索 - ES.Kibana.IK安装 ElasticSearch 实现分词全文检索 - Rest ...

  7. CF1801B题解

    CF1801B题解 传送门 更好的阅读体验 简化题意:有 n 个商店,每个商店卖 a,b 两种商品,价格分别为 \(a_i,b_i\),你需要在每个商店买一个商品,并且不能在所有商店都买同一种商品,最 ...

  8. Mysql 备份方案

    一.为什么要备份 [1]容灾恢复:硬件故障.不经意的 Bug 导致数据损坏,或者服务器及其数据由于某些原因不可获取或无法使用等(例如:机房大楼烧毁,恶意的黑客攻击或 Mysql 的 Bug 等).[2 ...

  9. Go 语言 new 和 make 关键字的区别

    原文链接: Go 语言 new 和 make 关键字的区别 本篇文章来介绍一道非常常见的面试题,到底有多常见呢?可能很多面试的开场白就是由此开始的.那就是 new 和 make 这两个内置函数的区别. ...

  10. springsecurity-jwt整合

    2 springsecurity-jwt整合 欢迎关注博主公众号「Java大师」, 专注于分享Java领域干货文章http://www.javaman.cn/sb2/jwt 2.1整合springse ...