1

I have an array A with elements size <= 10^6.

I want to implement a data structure which gives me sum of all elements less thank k in a particular range say l to r.

I know it can be solved using segment tree but dont know how to maintain segment tree for variable k queries. Please help me with pseudo code.

As there are no updates I think Mo's Algorithms could also be used.

alex
  • 39
  • 4
  • @Primusa Are you sure you read the question right? I don't see how your suggestion solves it. At least not if there are many such queries. – btilly Oct 08 '19 at 21:25
  • 1
    @btilly before I was sure now not anymore :). Perhaps you can try a segment tree with a BST in every node? Each layer of the segment tree has N elements total so total time to build is O(NlogN) per layer times O(logN) layers so O(NlogNlogN). I think finding the sum of elements < K in a BST can be done in O(logN) if you preprocess and you will have to visit up to logN BSTs so O(logNlogN) per query – Primusa Oct 08 '19 at 21:39
  • 1
    Actually you don't need a BST, a sorted array would do since you don't have updates, and then you can use prefix sums to get the sum. – Primusa Oct 08 '19 at 21:41
  • @Primusa how will i maintain range queries using sorted array – alex Oct 09 '19 at 04:23

2 Answers2

1

Below assumes the elements in your array are all positive

how about not maintaining segment tree for specific k but resolving the query instead

Just consider your segment tree.

At each node Node_i, you know:

  • its covering sum: s_i
  • the number of elements it covers: n_i

So two steps:

  1. For a given range query, get down to the corresponding node Node_i.
  2. For that Node_i, s_i is the sum of its two children's sum. For each of those given child Node_j with its n_j elements covered: two possibilities
    • n_j*k < s_j :all elements are less than k
    • n_j*k >= s_j:at least one element is greater or equal than k

So first case, the child's sum is already valid, nothing more to do.

Second case, you have to explore the child and so forth until nothing more to do

At some point, (if you have an invalid element) you will reach a bottom of the tree: that very node (also an elem) is bad, and you backtrack that fact. When you get back to your node Node_i, you substract from s_i all those bad leaf node's value you found.

pseudo code is:

#node is like: 
#children:[c1, c2]
#n:number of elem covered
#sum: sum of all elemens it covers
#returns the sum of the covered elements whose value is __greater__ or equal than k
def explore(node, k):
    #terminal case
    if node.n == 1:
        if node.sum >= k:
            return node.sum
        # when the range query is of size 1..., 
        # you may want to handle that elsewhere (e.g before calling explore)
        return 0
    end

    #standard case
    [c1,c2] = node.children
    totalsum = 0
    if c1.n * k < c1.sum
        #all your elems are less than k, substract nothing
        totalsum += 0 
    else
        totalsum += explore(c1, k)
    #same for c2...
    return totalsum
grodzi
  • 5,633
  • 1
  • 15
  • 15
0

If your k is fixed you can map array values as follows: If element is less than k put that value in leaf, else put 0. Then you can use standard sum function because all elements that are greater than k will be 0 in leafs and won't affect sum.

NO ONE
  • 33
  • 6