Maximum sub-array sum after dividing array into sub-arrays based on the given queries
Last Updated :
08 May, 2023
Given an array arr[] and an integer k, we can cut this array at k different positions where k[] stores the positions of all the cuts required. The task is to print maximum sum among all the cuts after every cut made. Every cut is of the form of an integer x where x denotes a cut between arr[x] and arr[x + 1].
Examples:
Input: arr[] = {4, 5, 6, 7, 8}, k[] = {0, 2, 3, 1}
Output: 26 15 11 8
First cut -> {4} and {5, 6, 7, 8}. Maximum possible sum is 5 + 6 + 7 + 8 = 26
Second cut -> {4}, {5, 6} and {7, 8}. Maximum sum = 15
Third cut -> {4}, {5, 6}, {7} and {8}. Maximum sum = 11
Fourth cut -> {4}, {5}, {6}, {7} and {8}. Maximum sum = 8
Input: arr[] = {1, 2, 3}, k[] = {1}
Output: 3
Naive approach: Store the resulting pieces of the array in an ArrayList and after every cut compute linearly the maximum possible sum. But this method would require O(n*k) time to answer all the queries. Efficient approach: We can represent each resulting piece of the array as a Piece object with data members start (start index of this piece), end (end index of this piece) and value (sum value of this piece). We can store these pieces in a TreeSet and sort them by their sum values. Therefore, after every cut we can get the Piece with largest sum value in O(log(n)).
- We have to make a prefix sum array of the array values to get the sum between two indices in constant time.
- We have to maintain another TreeSet with start indexes of all the current pieces so that we can find the exact piece to cut. For example, for a single piece:
- {1, 8} -> start = 1, end = 2, value = 9 and {6, 3, 9} -> start = 3, end = 5, value = 18.
- In order to cut index 4, we need to cut the second piece into two pieces as {6, 3} ans {9}. So we get the start index of which piece to cut from this TreeSet.
Below is the implementation of the above approach:
Java
// Java implementation of the approach
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
// Comparator to sort the Pieces
// based on their sum values
class MyComp implements Comparator<Piece> {
public int compare(Piece p1, Piece p2)
{
if (p2.val != p1.val)
return p2.val - p1.val;
if (p1.start != p2.start)
return p2.start - p1.start;
return 0;
}
}
class Piece {
int start;
int end;
int val;
// Constructor to initialize each Piece
Piece(int s, int e, int v)
{
start = s;
end = e;
val = v;
}
}
class GFG {
// Function to perform the given queries on the array
static void solve(int n, int k, int cuts[], int A[])
{
// Prefix sum array
int sum[] = new int[n];
sum[0] = A[0];
for (int i = 1; i < n; i++)
sum[i] = sum[i - 1] + A[i];
// TreeSet storing all the starts
TreeSet<Integer> t = new TreeSet<>();
// TreeSet storing the actual pieces
TreeSet<Piece> pq = new TreeSet<>(new MyComp());
Piece temp[] = new Piece[n];
temp[0] = new Piece(0, n - 1, sum[n - 1]);
// Added the whole array or Piece of array
// as there is no cuts yet
pq.add(temp[0]);
t.add(0);
for (int i = 0; i < k; i++) {
// curr is the piece to be cut
int curr = t.floor(cuts[i]);
pq.remove(temp[curr]);
int end = temp[curr].end;
// When a piece with start = s and end = e
// is cut at index i, two pieces are created with
// start = s, end = i and start = i + 1 and end = e
// We remove the previous piece and add
// this one to the TreeSet
temp[curr]
= new Piece(curr, cuts[i],
sum[cuts[i]]
- (curr == 0 ? 0 : sum[curr - 1]));
pq.add(temp[curr]);
temp[cuts[i] + 1]
= new Piece(cuts[i] + 1,
end, sum[end] - sum[cuts[i]]);
pq.add(temp[cuts[i] + 1]);
t.add(curr);
t.add(cuts[i] + 1);
System.out.println(pq.first().val);
}
}
// Driver code
public static void main(String[] args)
{
int A[] = { 4, 5, 6, 7, 8 };
int n = A.length;
int cuts[] = { 0, 2, 3, 1 };
int k = cuts.length;
solve(n, k, cuts, A);
}
}
Python3
# Python implementation of the approach
from functools import cmp_to_key
# Comparator to sort the Pieces
# based on their sum values
def my_comp(p1, p2):
if p2.val != p1.val:
return p2.val - p1.val
if p1.start != p2.start:
return p2.start - p1.start
return 0
class Piece:
def __init__(self, s, e, v):
self.start = s
self.end = e
self.val = v
# Function to perform the given queries on the array
def solve(n, k, cuts, A):
# Prefix sum array
sum = [0] * n
sum[0] = A[0]
for i in range(1, n):
sum[i] = sum[i - 1] + A[i]
# TreeSet storing all the starts
t = set()
# TreeSet storing the actual pieces
pq = []
temp = [None] * n
temp[0] = Piece(0, n - 1, sum[n - 1])
# Added the whole array or Piece of array
# as there is no cuts yet
pq.append(temp[0])
t.add(0)
for i in range(k):
# curr is the piece to be cut
curr = max(t, key=lambda x: x if x <= cuts[i] else float('-inf'))
pq.remove(temp[curr])
end = temp[curr].end
# When a piece with start = s and end = e
# is cut at index i, two pieces are created with
# start = s, end = i and start = i + 1 and end = e
# We remove the previous piece and add
# this one to the TreeSet
temp[curr] = Piece(curr, cuts[i], sum[cuts[i]] - (0 if curr == 0 else sum[curr - 1]))
pq.append(temp[curr])
temp[cuts[i] + 1] = Piece(cuts[i] + 1, end, sum[end] - sum[cuts[i]])
pq.append(temp[cuts[i] + 1])
t.add(curr)
t.add(cuts[i] + 1)
pq.sort(key=cmp_to_key(my_comp))
print(pq[0].val)
# Driver code
if __name__ == '__main__':
A = [4, 5, 6, 7, 8]
n = len(A)
cuts = [0, 2, 3, 1]
k = len(cuts)
solve(n, k, cuts, A)
C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
// Comparator to sort the Pieces
// based on their sum values
class MyComp : IComparer<Piece> {
public int Compare(Piece p1, Piece p2)
{
if (p2.val != p1.val)
return p2.val - p1.val;
if (p1.start != p2.start)
return p2.start - p1.start;
return 0;
}
}
class Piece {
public int start;
public int end;
public int val;
// Constructor to initialize each Piece
public Piece(int s, int e, int v)
{
start = s;
end = e;
val = v;
}
}
class GFG {
// Function to perform the given queries on the array
static void solve(int n, int k, int[] cuts, int[] A)
{
// Prefix sum array
int[] sum = new int[n];
sum[0] = A[0];
for (int i = 1; i < n; i++)
sum[i] = sum[i - 1] + A[i];
// TreeSet storing all the starts
SortedSet<int> t = new SortedSet<int>();
// TreeSet storing the actual pieces
SortedSet<Piece> pq
= new SortedSet<Piece>(new MyComp());
Piece[] temp = new Piece[n];
temp[0] = new Piece(0, n - 1, sum[n - 1]);
// Added the whole array or Piece of array
// as there is no cuts yet
pq.Add(temp[0]);
t.Add(0);
for (int i = 0; i < k; i++) {
// curr is the piece to be cut
int curr
= t.GetViewBetween(int.MinValue, cuts[i])
.Max;
pq.Remove(temp[curr]);
int end = temp[curr].end;
// When a piece with start = s and end = e
// is cut at index i, two pieces are created
// with start = s, end = i and start = i + 1 and
// end = e We remove the previous piece and add
// this one to the TreeSet
temp[curr] = new Piece(
curr, cuts[i],
sum[cuts[i]]
- (curr == 0 ? 0 : sum[curr - 1]));
pq.Add(temp[curr]);
temp[cuts[i] + 1] = new Piece(
cuts[i] + 1, end, sum[end] - sum[cuts[i]]);
pq.Add(temp[cuts[i] + 1]);
t.Add(curr);
t.Add(cuts[i] + 1);
Console.WriteLine(pq.Min.val);
}
}
// Driver code
public static void Main(string[] args)
{
int[] A = { 4, 5, 6, 7, 8 };
int n = A.Length;
int[] cuts = { 0, 2, 3, 1 };
int k = cuts.Length;
// Function call
solve(n, k, cuts, A);
}
}
// This code is contributed by phasing17.
JavaScript
// javascript implementation of the approach
// Comparator to sort the Pieces
// based on their sum values
class Piece{
constructor(s, e, v){
this.start = s;
this.end= e;
this.val = v;
}
}
function upper_bound(t, x){
let a = Array.from(t);
a.sort();
let l = 0;
let h = a.length - 1;
while(l <= h){
let m = Math.floor((l+h)/2);
if(a[m] < x){
l = m + 1;
}
else if(a[m] == x) return a[m];
else h = m - 1;
}
l--;
return a[l];
}
// Function to perform the given queries on the array
function solve(n, k, cuts, A){
// Prefix sum array
let sum = new Array(n).fill(0);
sum[0] = A[0];
for(let i = 1; i < n; i++){
sum[i] = sum[i-1] + A[i];
}
// TreeSet storing all the starts
let t = new Set();
// TreeSet storing the actual pieces
let pq = [];
let temp = new Array(n).fill(null);
temp[0] = new Piece(0, n - 1, sum[n - 1]);
// Added the whole array or Piece of array
// as there is no cuts yet
pq.push(temp[0]);
t.add(0);
for(let i = 0; i < k; i++){
// curr is the piece to be cut
// console.log(cuts + " " + i);
let curr = upper_bound(t, cuts[i]);
pq.splice(pq.indexOf(temp[curr]), 1);
let end = temp[curr].end;
// When a piece with start = s and end = e
// is cut at index i, two pieces are created with
// start = s, end = i and start = i + 1 and end = e
// We remove the previous piece and add
// this one to the TreeSet
temp[curr] = new Piece(curr, cuts[i], sum[cuts[i]] - ((curr == 0)? 0: sum[curr - 1]));
pq.push(temp[curr]);
temp[cuts[i] + 1] = new Piece(cuts[i] + 1, end, sum[end] - sum[cuts[i]]);
pq.push(temp[cuts[i] + 1]);
t.add(curr);
t.add(cuts[i] + 1);
pq.sort(function(p1, p2){
if(p2.val != p1.val)
return p2.val - p1.val;
if(p1.start != p2.start)
return p2.start - p1.start;
return 0;
})
console.log(pq[0].val);
}
}
// #Driver code
let A = [4, 5, 6, 7, 8];
let n = A.length
let cuts = [0, 2, 3, 1];
let k = cuts.length;
solve(n, k, cuts, A);
// The code is contributed by Nidhi goel.
Time Complexity O(n + k Log n)
Space Complexity: O(n + k)
Similar Reads
Find the maximum sum after dividing array A into M Subarrays Given a sorted array A[] of size N and an integer M. You need to divide the array A[] into M non-empty consecutive subarray (1 ? M ? N) of any size such that each element is present in exactly one of the M-subarray. After dividing the array A[] into M subarrays you need to calculate the sum [max(i)
10 min read
Maximum sum obtained by dividing Array into several subarrays as per given conditions Given an array arr[] of size N, the task is to calculate the maximum sum that can be obtained by dividing the array into several subarrays(possibly one), where each subarray starting at index i and ending at index j (j>=i) contributes arr[j]-arr[i] to the sum. Examples: Input: arr[]= {1, 5, 3}, N
5 min read
Queries to find maximum sum contiguous subarrays of given length in a rotating array Given an array arr[] of N integers and Q queries of the form {X, Y} of the following two types: If X = 1, rotate the given array to the left by Y positions.If X = 2, print the maximum sum subarray of length Y in the current state of the array. Examples: Input: N = 5, arr[] = {1, 2, 3, 4, 5}, Q = 2,
13 min read
Maximum sum of segments among all segments formed in array after Q queries Given two arrays arr[](1-based indexing) and queries[] consisting of N integers and queries[] contains a permutation of the first N natural numbers, the task is to perform the query on the array and find the maximum sum of segments among all segments formed such that in each query queries[i] the arr
15 min read
Maximize Array sum by adding multiple of another Array element in given ranges Given two arrays X[] and Y[] of length N along with Q queries each of type [L, R] that denotes the subarray of X[] from L to R. The task is to find the maximum sum that can be obtained by applying the following operation for each query: Choose an element from Y[]. Add multiples with alternate +ve an
15+ min read