2

Given an array 'A' of size 'N' containing integers. You need to answer 'Q' queries of type [ L R X Y ]. In each of the query you need to select at least 'X' elements and at most 'Y' elements from range 'L' to 'R' of the array 'A' such that their sum is maximum.

Output the maximum sum achievable for each of the query.

Example :

N = 5 
A = [ 1, 2, -1, -2, 3 ]
Q = [ [ 1, 3, 1, 2 ] , [ 3, 4, 1, 2 ] ]

Output : 3, -1

Expanation :

For query 1, we select integers 1 and 2 to get the sum 3. This is the maximum sum achievable in the range index 1 to 3.

For query 2, we need to select at least 1 element so we select -1 to get maximum sum -1.

Note :

The selected elements in the range L to R need not be consecutive. You can > select subsequence of integers to maximise the sum.

Constraints :

1<=N<=10^5
1<=Q<=10^5
-10^8 <= A[i] <= 10^8
1<=L<=R<=N
1<=X<=Y<=R-L+1

I tried to think of some approaches but could not find any algo for the above constraints. Any help/hint would be appreciated.

raxona3dd
  • 23
  • 4
  • Do the selected numbers have to be next to each other? If not, just select the `X` largest elements, then continue adding the next-largest elements until you have `Y` or the next selected element would be negative. – tobias_k May 20 '22 at 18:35
  • No the elements need not be adjacent. But how to implement your approach in the given constraints. Which algorithm will you use to select X largest elements and what is your expected time complexity for the same. @tobias_k – raxona3dd May 20 '22 at 18:41
  • In the constraints, is `10^-8` supposed to be `-10^8`? – user3386109 May 20 '22 at 18:45
  • yes @user3386109, corrected that. Sorry for the confusion. – raxona3dd May 20 '22 at 18:48
  • You never want negative numbers in the sum, so the first step is to determine how many positive (including 0) numbers are in the range. This can be done with an array `C` where `C[i]` is the count of positive numbers in the range 1 to `i`. So given the range L to R, the count of positive numbers is `Z = C[R] - C[L-1]`. If `Z >= X` then you'll take only positive numbers in the range. Otherwise, you take all of the positive numbers plus `X - Z` negative numbers. – user3386109 May 20 '22 at 19:00
  • @user3386109 thanks for replying but lets say for case X<=Z, we need to then select min(Z,Y) maximum positive integers in the range L to R. Now how to solve this in the given constraints is the main problem. Sameways for the other case X>Z we need to take X-Z maximum negative integers so for every range how to compute that without exceeding Time Limit. – raxona3dd May 20 '22 at 19:07
  • This is a competitive programming problem, can you share the original problem link? – जलजनक May 20 '22 at 19:15
  • For "my approach" (which is apparently not what you need) you'd just sort the list, then select x to y elements; time complexity would be O(nlogn) for the sorting step. – tobias_k May 20 '22 at 19:16
  • @जलजनक this is a CP problem but I didn't find it on platform. It was in one of my interview so I tried to upsolve but I'm unable to so asking for help here. The interview contest took place on Hackerrank previous week. – raxona3dd May 20 '22 at 19:18

1 Answers1

1

One approach is to preprocess the numbers by splitting into non-overlapping arrays of length L (for L equal to different powers of 2).

Sort each array, and compute the cumulative sum of each array.

Then for each query, identify the arrays which combine to make the query range and use bisection to identify the level T such that if taking all elements above T we end up with a legal number of elements and the highest sum.

There will be log(N) arrays involved, and log(N) steps in each bisection, so this should be reasonably fast.

(Note if our first evaluation shows that taking all positive elements ends up with too many, we need to find the lowest legal level by bisection, while if we end up with too few we need to find the highest legal level by bisection)

Example

Suppose we have an array A = [ 1, -1, 2, -2, 3, -3, 4, 0 ]. The preprocessing will split it into:

Two arrays of length 4: [ 1, -1, 2, -2], [ 3, -3, 4, 0 ]
Four arrays of length 2: [ 1, -1], [2, -2], [ 3, -3], [4, 0 ]
Eight arrays of length 1: [1], [-1], [2], [-2], [ 3], [-3], [4], [0 ]

Then with a query 3 to 5, we want the elements [-2,3,-3] which we can form from the arrays [-2] and [3,-3].

Suppose we now want to find the maximum sum from at least 2 elements.

We first try taking all positive elements, this only results in 1 element so we know we need to bisect for the highest legal level.

The bisection could work by trying some values, e.g.

All elements >= 0 gives 1 element, so value is too high
All elements >= -4 gives 3 elements, so value is too low
All elements >= -2 gives 2 elements, so value is just right
Peter de Rivaz
  • 33,126
  • 4
  • 46
  • 75
  • Hi your approach looks really fast but I am unable to understand the biscetion part. Here is what I have understood overall and what is left. lets say we have A = [ 1, -1, 2, -2, 3, -3, 4 ]. So we partition it as P = [ 1 ], [ -1, 2 ] , [ -2, 3, -3, 4 ]. Then we sort these individual components = [ 1 ] , [ 2, -1 ] , [ 4, 3, -2, -3 ]. Then we take cumulative sum of individual components = [ 1 ], [ 2, 1 ] , [ 4, 7, 5, 2 ] Now lets say our query is [ 3, 5, 1, 2 ]. So we select the components that fall within this query = [ 3,3 ] + [ 4,5 ]. Now how to proceed ahead I am unable to get that part. – raxona3dd May 21 '22 at 02:29
  • Did I get the above part correct till now ? I also studied the Bisection method which is to find the approximate roots of a quadratic equation where we start with two points 'a' and 'b' such that f(a)*f(b)<0 but how is it useful here ? Here there are K components such that 'K' <= log(N) and we need to select some prefixes { x1, x2, ... xK } from them such that L<=x1+x2+... + xK<=R and sum is maximised. Help in approaching ahead. @Peter de Rivaz – raxona3dd May 21 '22 at 02:33
  • I've added an example showing how the range can be broken into sub arrays. – Peter de Rivaz May 21 '22 at 10:57
  • Thanks a lot for clarifying and sorry for disturbing but it would be really helpful if you can also show in the example how u intend to select the maximum among different components. Like in your example the arrays for query 3 to 5 are = [ -2 ] , [ 3, -3 ] and if we need to select minimum 2 elements then we would select 3 and -2. So how to implement this in algorithm is still unclear to me. – raxona3dd May 21 '22 at 18:29
  • I've added an example showing how to bisect for the target in the example – Peter de Rivaz May 22 '22 at 14:33