2022-12-16:给你一个长度为n的数组,并询问q次 每次询问区间[l,r]之间是否存在小于等于k个数的和大于等于x 每条查询返回true或者false。 1 <= n, q <= 10^5 k
Posted 福大大架构师每日一题
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022-12-16:给你一个长度为n的数组,并询问q次 每次询问区间[l,r]之间是否存在小于等于k个数的和大于等于x 每条查询返回true或者false。 1 <= n, q <= 10^5 k相关的知识,希望对你有一定的参考价值。
2022-12-16:给你一个长度为n的数组,并询问q次
每次询问区间[l,r]之间是否存在小于等于k个数的和大于等于x
每条查询返回true或者false。
1 <= n, q <= 10^5
k <= 10
1 <= x <= 10^8。
答案2022-12-16:
线段树。
代码用go语言编写。代码如下:
package main
import (
"fmt"
"math/rand"
"sort"
"time"
)
func main()
rand.Seed(time.Now().Unix())
N := 100
K := 10
V := 100
testTimes := 5000
queryTimes := 100
fmt.Println("测试开始")
for i := 0; i < testTimes; i++
n := rand.Intn(N) + 1
k := rand.Intn(K) + 1
arr := randomArray(n, V)
st := NewSegmentTree(arr, k)
right := NewRight(arr, k)
for j := 0; j < queryTimes; j++
a := rand.Intn(n)
b := rand.Intn(n)
l := GetMin(a, b)
r := GetMax(a, b)
ans1 := st.topKSum(l, r)
ans2 := right.topKSum(l, r)
if ans1 != ans2
fmt.Println("出错了!")
fmt.Println(ans1)
fmt.Println(ans2)
break
fmt.Println("测试结束")
func GetMax(a, b int) int
if a > b
return a
else
return b
func GetMin(a, b int) int
if a < b
return a
else
return b
type SegmentTree struct
n int
k int
// private int[] max;
// private int[][] max = new int[][10];
max [][]int
query [][]int
func NewSegmentTree(arr []int, K int) *SegmentTree
n := len(arr)
k := K
max := make([][]int, (n+1)<<2)
query := make([][]int, (n+1)<<2)
for i := 0; i < len(max); i++
max[i] = make([]int, k)
query[i] = make([]int, k)
ans := &SegmentTree
ans.n = n
ans.k = k
ans.max = max
ans.query = query
for i := 0; i < n; i++
ans.update(i, arr[i])
return ans
func (this *SegmentTree) topKSum(l int, r int) int
this.collect(l+1, r+1, 1, this.n, 1)
sum := 0
for _, num := range this.query[1]
sum += num
return sum
func (this *SegmentTree) update(i int, v int)
this.update0(i+1, i+1, v, 1, this.n, 1)
func (this *SegmentTree) update0(L int, R int, C int, l int, r int, rt int)
if L <= l && r <= R
this.max[rt][0] = C
return
mid := (l + r) >> 1
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.merge(this.max[rt], this.max[rt<<1], this.max[rt<<1|1])
// father 要前k名
// left k名
// right k名
func (this *SegmentTree) merge(father []int, left []int, right []int)
for i, p1, p2 := 0, 0, 0; i < this.k; i++
if left == nil || p1 == this.k
father[i] = right[p2]
p2++
else if right == nil || p2 == this.k
father[i] = left[p1]
p1++
else
if left[p1] >= right[p2]
father[i] = left[p1]
p1++
else
father[i] = right[p2]
p2++
func (this *SegmentTree) collect(L int, R int, l int, r int, rt int)
if L <= l && r <= R
for i := 0; i < this.k; i++
this.query[rt][i] = this.max[rt][i]
else
mid := (l + r) >> 1
leftUpdate := false
rightUpdate := false
if L <= mid
leftUpdate = true
this.collect(L, R, l, mid, rt<<1)
if R > mid
rightUpdate = true
this.collect(L, R, mid+1, r, rt<<1|1)
var left []int = nil
if leftUpdate
left = this.query[rt<<1]
var right []int = nil
if rightUpdate
right = this.query[rt<<1|1]
this.merge(this.query[rt], left, right)
// // 暴力实现的结构
// // 为了验证
type Right struct
arr []int
k int
func NewRight(nums []int, K int) *Right
k := K
arr := make([]int, len(nums))
for i := 0; i < len(nums); i++
arr[i] = nums[i]
return &Rightarr: arr, k: k
func (this *Right) topKSum(l int, r int) int
heap := make([]int, 0)
for i := l; i <= r; i++
heap = append(heap, this.arr[i])
sum := 0
for i := 0; i < this.k && len(heap) > 0; i++
sort.Slice(heap, func(i, j int) bool
return heap[i] > heap[j]
)
sum += heap[0]
heap = heap[1:]
return sum
// 为了验证
func randomArray(n int, v int) []int
ans := make([]int, n)
for i := 0; i < n; i++
ans[i] = rand.Intn(v) + 1
return ans
执行结果如下:
以上是关于2022-12-16:给你一个长度为n的数组,并询问q次 每次询问区间[l,r]之间是否存在小于等于k个数的和大于等于x 每条查询返回true或者false。 1 <= n, q <= 10^5 k的主要内容,如果未能解决你的问题,请参考以下文章
2022-06-14:数组的最大与和。 给你一个长度为 n 的整数数组 nums 和一个整数 numSlots ,满足2 * numSlots >= n 。总共有 numSlots 个篮子,编号为 1
2021-10-29:除自身以外数组的乘积。给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之
风口之下,猪都能飞。当今中国股市牛市,真可谓“错过等七年”。 给你一个回顾历史的机会,已知一支股票连续n天的价格走势,以长度为n的整数数组表示,
风口之下,猪都能飞。当今中国股市牛市,真可谓“错过等七年”。 给你一个回顾历史的机会,已知一支股票连续n天的价格走势,以长度为n的整数数组表示,
2022-03-07:K 个关闭的灯泡。 N 个灯泡排成一行,编号从 1 到 N 。最初,所有灯泡都关闭。每天只打开一个灯泡,直到 N 天后所有灯泡都打开。 给你一个长度为 N 的灯泡数组 blubs
2022-10-30:给你一个长度为 n 的整数数组 rolls 和一个整数 k 。 你扔一个 k 面的骰子 n 次,骰子的每个面分别是 1 到 k , 其中第 i 次扔得到的数字是 rolls[i]