2021-11-27:给定一个数组arr,长度为N,做出一个结构,可以高效的做如下的查询: 1) int querySum(L,R) : 查询arr[L...R]上的累加和; 2) int query
2021-11-27:给定一个数组arr,长度为N,做出一个结构,可以高效的做如下的查询:
- int querySum(L,R) : 查询arr[L…R]上的累加和;
- int queryAim(L,R) : 查询arr[L…R]上的目标值,目标值定义如下:
假设arr[L…R]上的值为[a,b,c,d],a+b+c+d = s,
目标值为 : (s-a)^2 + (s-b)^2 + (s-c)^2 + (s-d)^2; - int queryMax(L,R) : 查询arr[L…R]上的最大值.
要求: - 初始化该结构的时间复杂度不能超过O(N*logN);
- 三个查询的时间复杂度不能超过O(logN);
- 查询时,认为arr的下标从1开始,比如 :
arr = [ 1, 1, 2, 3 ];
querySum(1, 3) -> 4;
queryAim(2, 4) -> 50;
queryMax(1, 4) -> 3。
来自美团。
答案2021-11-27:
querySum方法,前缀和。
queryAim方法,前缀和,平方数组的前缀和,线段树。对目标值展开,(N-2)*S平方+a1的平方+a2的平方+…+an的平方。
queryMax方法,线段树。
代码用golang编写。代码如下:
package main
import (
"fmt"
"math"
)
func main() {
q := NewQuery([]int{1, 2, 3, 4, 5})
ret := 0
ret = q.querySum(1, 3)
fmt.Println(ret)
ret = q.queryAim(1, 3)
fmt.Println(ret)
ret = q.queryMax(1, 3)
fmt.Println(ret)
}
type SegmentTree struct {
max []int
change []int
update []bool
}
func NewSegmentTree(N int) *SegmentTree {
ret := &SegmentTree{}
ret.max = make([]int, N<<2)
ret.change = make([]int, N<<2)
ret.update = make([]bool, N<<2)
for i := 0; i < len(ret.max); i++ {
ret.max[i] = math.MinInt64
return ret
}
return ret
}
func (this *SegmentTree) pushUp(rt int) {
this.max[rt] = getMax(this.max[rt<<1], this.max[rt<<1|1])
}
func getMax(a int, b int) int {
if a > b {
return a
} else {
return b
}
}
// ln表示左子树元素结点个数,rn表示右子树结点个数
func (this *SegmentTree) pushDown(rt, ln, rn int) {
if this.update[rt] {
this.update[rt<<1] = true
this.update[rt<<1|1] = true
this.change[rt<<1] = this.change[rt]
this.change[rt<<1|1] = this.change[rt]
this.max[rt<<1] = this.change[rt]
this.max[rt<<1|1] = this.change[rt]
this.update[rt] = false
}
}
func (this *SegmentTree) update0(L, R, C, l, r, rt int) {
if L <= l && r <= R {
this.update[rt] = true
this.change[rt] = C
this.max[rt] = C
return
}
mid := (l + r) >> 1
this.pushDown(rt, mid-l+1, r-mid)
if L <= mid {
this.update0(L, R, C, l, mid, rt<<1)
}
if R > mid {
this.update0(L, R, C, mid+1, r, rt<<1|1)
}
this.pushUp(rt)
}
func (this *SegmentTree) query(L, R, l, r, rt int) int {
if L <= l && r <= R {
return this.max[rt]
}
mid := (l + r) >> 1
this.pushDown(rt, mid-l+1, r-mid)
left := 0
right := 0
if L <= mid {
left = this.query(L, R, l, mid, rt<<1)
}
if R > mid {
right = this.query(L, R, mid+1, r, rt<<1|1)
}
return getMax(left, right)
}
type Query struct {
sum1 []int
sum2 []int
st *SegmentTree
m int
}
func NewQuery(arr []int) *Query {
ret := &Query{}
n := len(arr)
ret.m = len(arr) + 1
ret.sum1 = make([]int, ret.m)
ret.sum2 = make([]int, ret.m)
ret.st = NewSegmentTree(ret.m)
for i := 0; i < n; i++ {
ret.sum1[i+1] = ret.sum1[i] + arr[i]
ret.sum2[i+1] = ret.sum2[i] + arr[i]*arr[i]
ret.st.update0(i+1, i+1, arr[i], 1, ret.m, 1)
}
return ret
}
func (this *Query) querySum(L, R int) int {
return this.sum1[R] - this.sum1[L-1]
}
func (this *Query) queryAim(L, R int) int {
sumPower2 := this.querySum(L, R)
sumPower2 *= sumPower2
return this.sum2[R] - this.sum2[L-1] + (R-L-1)*sumPower2
}
func (this *Query) queryMax(L, R int) int {
return this.st.query(L, R, 1, this.m, 1)
}
执行结果如下:

2021-11-27:给定一个数组arr,长度为N,做出一个结构,可以高效的做如下的查询: 1) int querySum(L,R) : 查询arr[L...R]上的累加和; 2) int query的更多相关文章
- delphi 判断一个数组的长度用 Length 还是 SizeOf ?
判断一个数组的长度用 Length 还是 SizeOf ?最近发现一些代码, 甚至有一些专家代码, 在遍历数组时所用的数组长度竟然是 SizeOf(arr); 这不合适! 如果是一维数组.且元素大小是 ...
- 判断一个数组的长度用 Length 还是 SizeOf ?
最近发现一些代码, 甚至有一些专家代码, 在遍历数组时所用的数组长度竟然是 SizeOf(arr); 这不合适! 如果是一维数组.且元素大小是一个字节, 这样用看不出错误, 譬如: var arr ...
- java 一个数组的长度
package java03; /* *如何获取数组长度 : * 格式: * 数组名称.length * * 这会得到一个int数字,代表数组的长度 * * 数组一旦创建,程序运行期间,长度不可改变 ...
- Solution -「2021.11.27」\Infty
T1. 显然往 \(x < 0, y < 0\) 的点走一定不优. 根据转移式可发现 \(C(x, y)\) 即从 \((0, 0)\) 走到 \((x, y)\) 的方案数 \(\dbi ...
- smarty中判断一个变量是否存在于一个数组中或是否存在于一个字符串中?
smarty支持php的系统函数可以直接使用{if in_array($str, $arr) || strpos($str, $string)} yes {else} no{/if}
- Java 高效检查一个数组中是否包含某个值
如何检查一个数组(未排序)中是否包含某个特定的值?在Java中,这是一个非常有用并又很常用的操作.同时,在StackOverflow中,有时一个得票非常高的问题.在得票比较高的几个回答中,时间复杂度差 ...
- splice() 方法通过删除现有元素和/或添加新元素来更改一个数组的内容。
var myFish = ["angel", "clown", "mandarin", "surgeon"]; //从第 ...
- 包含MIN函数的栈+一个数组实现两个堆栈+两个数组实现MIN栈
1.题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数. 思路:利用一个辅助栈来存放最小值 栈 3,4,2,5,1 辅助栈 3,2,1 每入栈一次,就与辅 ...
- 华为机试001:字符串最后一个单词的长度(华为OJ001)
华为机试 字符串最后一个单词的长度 计算字符串最后一个单词的长度,单词以空格隔开. 提交网址: http://www.nowcoder.com/practice/8c949ea5f36f422594b ...
- 【es6】将2个数组合并为一个数组
//第一种 一个数组中的值为key 一个数组中的值为value let arr1 = ['内存','颜色','尺寸']; let arr2 = [1,2,3]; let temp = arr1.map ...
随机推荐
- python内置函数range()—对象创建函数
range()函数 介绍 range()函数实际上表示一个不可变的数字序列类型,通常用于在for循环中指定特定的次数. range()的格式: range(stop) range(start, sto ...
- python内置函数map()
map()函数 介绍 map()是python的一个内置函数,其作用是返回一个迭代器,该迭代器将function函数应用于可迭代对象的每个项,并产生结果. map函数的语法: map(function ...
- 痞子衡嵌入式:分享一个i.MXRT系列配套DRAM压力测试上位机工具(i.MXRT DRAM Tester)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦SE团队制作的i.MXRT配套DRAM压力测试上位机工具. 事情源于痞子衡的技术交流群里的提问,有群友在恩智浦官方技术公众号 [恩 ...
- 使用OpenOffice将office文件转为pdf
0.参考博客:https://blog.csdn.net/weixin_39468112/article/details/89203815 1.首先安装openOffice4.1 2.添加依赖 < ...
- App 用户新体验——Agora Native SDK 3.4.0
声网Agora Native SDK 3.4.0 本月已正式上线.新版本不仅增加了更丰富的实时美声音效.屏幕共享.虚拟节拍器等功能,同时在 SDK 的稳定性.兼容性及安全合规上做了大幅度升级,希望为 ...
- 详解DDD:如何避免写流水账代码?
在日常工作中我观察到,面对老系统重构和迁移场景,有大量代码属于流水账代码,通常能看到开发在对外的API接口里直接写业务逻辑代码,或者在一个服务里大量的堆接口,导致业务逻辑实际无法收敛,接口复用性比较差 ...
- 恰好经过k条边的最短路
需要用到离散数学中关于关系矩阵的运算的知识 一个表示一个图中任意两点间经过2条边最短路的关系矩阵的平方表示的是任意两点间经过4条边的最短路的关系矩阵 原因在于当我们选定中间点时,路径的前半部分和后半部 ...
- 最强分布式搜索引擎——ElasticSearch
最强分布式搜索引擎--ElasticSearch 本篇我们将会介绍到一种特殊的类似数据库存储机制的搜索引擎工具--ES elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以 ...
- markdown---->Typora搭配uPic
记录一下在mac上面使用Typora和uPic来发表博客的过程,图床用的是阿里Oss.We all, whether we know it or not, are fighting to make t ...
- JS - new Function
Function 在JavaScript当中,除了可以使用function或箭头函数定义方法外,还可以使用new Function的形式动态创建函数,此时与eval()方法类似 创建一个不接收参数的方 ...