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


执行结果如下:


左神java代码

以上是关于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]