CSES Solutions – Sliding Window Cost
Last Updated :
16 Mar, 2024
You are given an array arr[] of N integers. Your task is to calculate for each window of K elements, from left to right, the minimum total cost of making all elements equal. You can increase or decrease each element with cost X, where X is the difference between the new and the original value. The total cost is the sum of such costs.
Examples:
Input: N = 4, K = 3, arr[] = {8, 4, 2, 4}
Output: 6 2
Explanation:
- The first window: {8, 4, 2}, make all the elements equal to 4, hence the total cost will be abs(8 – 4) + abs(4 – 4) + abs(2 – 4) = 6.
- The second window: {4, 2, 4}, make all the elements equal to 4, hence the total cost will be abs(4 – 4) + abs(2 – 4) + abs(4 – 4) = 2.
Input: N = 8, K = 3, arr[] = {2, 4, 3, 5, 8, 1, 2, 1}
Output: 2 2 5 7 7 1
Explanation:
- The first window: {2, 4, 3}, make all the elements equal to 3, hence the total cost will be abs(2 – 3) + abs(4 – 3) + abs(3 – 3) = 0.
- The second window: {4, 3, 5}, make all the elements equal to 4, hence the total cost will be abs(4 – 4) + abs(3 – 4) + abs(5 – 4) = 2.
- The third window: {3, 5, 8}, make all the elements equal to 5, hence the total cost will be abs(3 – 5) + abs(5 – 5) + abs(8 – 5) = 5.
- The fourth window: {5, 8, 1}, make all the elements equal to 5, hence the total cost will be abs(5 – 5) + abs(8 – 5) + abs(1 – 5) = 7.
- The fifth window: {8, 1, 2}, make all the elements equal to 2, hence the total cost will be abs(8 – 2) + abs(1 – 2) + abs(2 – 2) = 7.
- The sixth window: {1, 2, 1}, make all the elements equal to 1, hence the total cost will be abs(1 – 1) + abs(2 – 1) + abs(1 – 1) = 1.
Approach: To solve the problem, follow the below idea:
The idea is to make all the elements equal to the median of the K size window. For determining the median of each window of size K, we will use two multisets. For a k size window, the first multiset will contain ceil(K/2) smallest elements and second multiset will contain K/2 largest elements of the window. By this way the median of the window will be equal to the largest element of the first multiset.
Now the cost to make all the elements equal will be:
= Cost of making elements of first multiset equal to Median + Cost of making elements of second multiset equal to Median
=[Tex]\Sigma\, (Median-lwr_{i})\, +\,\Sigma\, (upr_{j}-Median)[/Tex] , for each i from 1 to ceil(k/2) and for each j from 1 to k/2, where Median is the Median of the current window, lwr and upr contains the elements of first and second multisets respectively.
The equation can be further simplified, making the total cost equal to
= (size of first multiset) * Median – (Sum of elements of first multiset) +
(Sum of elements of second multiset) – (size of second multiset) * Median
Follow the steps to solve the problem:
- Use two multisets (
lwr
and upr
) to maintain the smallest and largest elements of the current window. Initialize variables sum1
and sum2
to keep track of the sum of elements in each multiset. - Iterate through the array using a loop.
- For each ith element, add it to the appropriate multiset and update the corresponding sum.
- To ensure that lwr multiset contains the smallest elements and upr multiset contains the largest elements, we do the following:
- Find the maximum from the multiset (
lwr
) and the minimum from the multiset (upr
). - If the maximum element from
lwr
is greater than the minimum element from upr
, swap them.
- Calculate the cost using the given formula:
((size of lwr) * Median - (sum1)) + ((sum2) - (size of upr) * Median)
- Output the calculated cost for each window.
Below is the implementation of above approach:
C++
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void SlidingCost(int N, int K, vector<ll>& arr)
{
// Initialize two multisets to maintain smallest (lwr)
// and largest (upr) elements
multiset<int> lwr, upr;
// Initialize sums of elements in lwr and upr multisets
ll sum1 = 0, sum2 = 0;
// Iterate through the array
for (int i = 0; i < N; i++) {
// Remove the (i-k)th element so that window
// conatins k elements
if (i >= K) {
if (lwr.find(arr[i - K]) != lwr.end()) {
lwr.erase(lwr.find(arr[i - K]));
sum1 = sum1 - arr[i - K];
}
else {
upr.erase(upr.find(arr[i - K]));
sum2 = sum2 - arr[i - K];
}
}
// Calculate sizes of lwr and upr multisets
ll sz1 = lwr.size(), sz2 = upr.size();
// Insert the current element into the appropriate
// multiset and update the sum
if (sz1 <= sz2) {
lwr.insert(arr[i]);
sum1 = sum1 + arr[i];
}
else {
upr.insert(arr[i]);
sum2 = sum2 + arr[i];
}
// Calculate sizes of lwr and upr multisets
sz1 = lwr.size(), sz2 = upr.size();
// Ensure that lwr multiset contains the smallest
// elements and upr multiset contains the largest
// elements
if (sz1 > 0 && sz2 > 0) {
// Find the maximum from lwr and the minimum
// from upr
auto max_lwr = lwr.rbegin();
auto min_upr = upr.begin();
// If the maximum element from lwr is greater
// than the minimum element from upr, swap them.
if (*max_lwr > *min_upr) {
sum1 = sum1 + (*min_upr - *max_lwr);
sum2 = sum2 + (*max_lwr - *min_upr);
lwr.insert(*min_upr);
upr.insert(*max_lwr);
upr.erase(upr.find(*min_upr));
lwr.erase(lwr.find(*max_lwr));
}
}
// Output the calculated cost for the current window
if (i >= (K - 1)) {
ll median = *lwr.rbegin();
cout << (sz1 * median - sum1)
+ (sum2 - median * sz2)
<< " ";
}
}
}
// Driver Code
int main()
{
int N = 8, K = 3;
// Input array
vector<ll> arr = { 2, 4, 3, 5, 8, 1, 2, 1 };
// Call the SlidingCost function
SlidingCost(N, K, arr);
}
Java
// Java program for the above approach
import java.util.*;
public class GFG {
static void slidingCost(int N, int K,
ArrayList<Long> arr)
{
// Initialize two multisets to maintain smallest
// (lwr) and largest (upr) elements
TreeSet<Long> lwr = new TreeSet<>();
TreeSet<Long> upr = new TreeSet<>();
// Initialize sums of elements in lwr and upr
// multisets
long sum1 = 0, sum2 = 0;
// Iterate through the array
for (int i = 0; i < N; i++) {
// Remove the (i-k)th element so that window
// contains k elements
if (i >= K) {
if (lwr.contains(arr.get(i - K))) {
lwr.remove(arr.get(i - K));
sum1 = sum1 - arr.get(i - K);
}
else {
upr.remove(arr.get(i - K));
sum2 = sum2 - arr.get(i - K);
}
}
// Calculate sizes of lwr and upr multisets
int sz1 = lwr.size(), sz2 = upr.size();
// Insert the current element into the
// appropriate multiset and update the sum
if (sz1 <= sz2) {
lwr.add(arr.get(i));
sum1 = sum1 + arr.get(i);
}
else {
upr.add(arr.get(i));
sum2 = sum2 + arr.get(i);
}
// Calculate sizes of lwr and upr multisets
sz1 = lwr.size();
sz2 = upr.size();
// Ensure that lwr multiset contains the
// smallest elements and upr multiset contains
// the largest elements
if (sz1 > 0 && sz2 > 0) {
// Find the maximum from lwr and the minimum
// from upr
long max_lwr = lwr.last();
long min_upr = upr.first();
// If the maximum element from lwr is
// greater than the minimum element from
// upr, swap them.
if (max_lwr > min_upr) {
sum1 = sum1 + (min_upr - max_lwr);
sum2 = sum2 + (max_lwr - min_upr);
lwr.add(min_upr);
upr.add(max_lwr);
upr.remove(min_upr);
lwr.remove(max_lwr);
}
}
// Output the calculated cost for the current
// window
if (i >= (K - 1)) {
long median = lwr.last();
System.out.print((sz1 * median - sum1)
+ (sum2 - median * sz2)
+ " ");
}
}
}
// Driver Code
public static void main(String[] args)
{
int N = 8, K = 3;
// Input array
ArrayList<Long> arr = new ArrayList<>(
Arrays.asList(2L, 4L, 3L, 5L, 8L, 1L, 2L, 1L));
// Call the SlidingCost function
slidingCost(N, K, arr);
}
}
// This code is contributed by Susobhan Akhuli
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
public class GFG {
static void SlidingCost(int N, int K, List<long> arr)
{
// Initialize two SortedSets to maintain smallest
// (lwr) and largest (upr) elements
SortedSet<long> lwr = new SortedSet<long>();
SortedSet<long> upr = new SortedSet<long>();
// Initialize sums of elements in lwr and upr
// SortedSets
long sum1 = 0, sum2 = 0;
// Iterate through the array
for (int i = 0; i < N; i++) {
// Remove the (i-k)th element so that window
// contains k elements
if (i >= K) {
if (lwr.Contains(arr[i - K])) {
lwr.Remove(arr[i - K]);
sum1 -= arr[i - K];
}
else {
upr.Remove(arr[i - K]);
sum2 -= arr[i - K];
}
}
// Calculate sizes of lwr and upr SortedSets
int sz1 = lwr.Count, sz2 = upr.Count;
// Insert the current element into the
// appropriate SortedSet and update the sum
if (sz1 <= sz2) {
lwr.Add(arr[i]);
sum1 += arr[i];
}
else {
upr.Add(arr[i]);
sum2 += arr[i];
}
// Calculate sizes of lwr and upr SortedSets
sz1 = lwr.Count;
sz2 = upr.Count;
// Ensure that lwr SortedSet contains the
// smallest elements and upr SortedSet contains
// the largest elements
if (sz1 > 0 && sz2 > 0) {
// Find the maximum from lwr and the minimum
// from upr
long max_lwr = lwr.Max;
long min_upr = upr.Min;
// If the maximum element from lwr is
// greater than the minimum element from
// upr, swap them.
if (max_lwr > min_upr) {
sum1 += (min_upr - max_lwr);
sum2 += (max_lwr - min_upr);
lwr.Add(min_upr);
upr.Add(max_lwr);
upr.Remove(min_upr);
lwr.Remove(max_lwr);
}
}
// Output the calculated cost for the current
// window
if (i >= (K - 1)) {
long median = lwr.Max;
Console.Write((sz1 * median - sum1)
+ (sum2 - median * sz2)
+ " ");
}
}
}
static void Main(string[] args)
{
int N = 8, K = 3;
// Input array
List<long> arr
= new List<long>{ 2, 4, 3, 5, 8, 1, 2, 1 };
// Call the SlidingCost function
SlidingCost(N, K, arr);
}
}
// This code is contributed by Susobhan Akhuli
Javascript
let ans = "";
function slidingCost(N, K, arr) {
// Initialize two arrays to maintain smallest (lwr) and largest (upr) elements
let lwr = [];
let upr = [];
// Initialize sums of elements in lwr and upr arrays
let sum1 = 0;
let sum2 = 0;
// Iterate through the array
for (let i = 0; i < N; i++) {
// Remove the (i-K)th element so that window contains K elements
if (i >= K) {
let removedElement = arr[i - K];
if (lwr.includes(removedElement)) {
let index = lwr.indexOf(removedElement);
lwr.splice(index, 1);
sum1 -= removedElement;
} else {
let index = upr.indexOf(removedElement);
upr.splice(index, 1);
sum2 -= removedElement;
}
}
// Insert the current element into the appropriate array and update the sum
if (lwr.length <= upr.length) {
lwr.push(arr[i]);
sum1 += arr[i];
} else {
upr.push(arr[i]);
sum2 += arr[i];
}
// Ensure that lwr array contains the smallest elements and upr array contains the largest elements
if (lwr.length > 0 && upr.length > 0) {
// Find the maximum from lwr and the minimum from upr
let max_lwr = Math.max(...lwr);
let min_upr = Math.min(...upr);
// If the maximum element from lwr is greater than the minimum element from upr, swap them
if (max_lwr > min_upr) {
sum1 += (min_upr - max_lwr);
sum2 += (max_lwr - min_upr);
lwr.push(min_upr);
upr.push(max_lwr);
upr.splice(upr.indexOf(min_upr), 1);
lwr.splice(lwr.indexOf(max_lwr), 1);
}
}
// Output the calculated cost for the current window
if (i >= K - 1) {
let median = Math.max(...lwr);
ans += (lwr.length * median - sum1) + (sum2 - median * upr.length) + " ";
}
}
}
// Driver code
function main() {
const N = 8;
const K = 3;
// Input array
const arr = [2, 4, 3, 5, 8, 1, 2, 1];
// Call the slidingCost function
slidingCost(N, K, arr);
console.log(ans);
}
main();
Python3
from typing import List
from collections import deque
def sliding_cost(N: int, K: int, arr: List[int]) -> None:
# Initialize two deques to maintain smallest (lwr)
# and largest (upr) elements
lwr, upr = deque(), deque()
# Initialize sums of elements in lwr and upr deques
sum1, sum2 = 0, 0
# Iterate through the array
for i in range(N):
# Remove the (i-k)th element so that window
# contains k elements
if i >= K:
if arr[i - K] in lwr:
lwr.remove(arr[i - K])
sum1 -= arr[i - K]
else:
upr.remove(arr[i - K])
sum2 -= arr[i - K]
# Calculate sizes of lwr and upr deques
sz1, sz2 = len(lwr), len(upr)
# Insert the current element into the appropriate
# deque and update the sum
if sz1 <= sz2:
lwr.append(arr[i])
sum1 += arr[i]
else:
upr.append(arr[i])
sum2 += arr[i]
# Calculate sizes of lwr and upr deques
sz1, sz2 = len(lwr), len(upr)
# Ensure that lwr deque contains the smallest
# elements and upr deque contains the largest
# elements
if sz1 > 0 and sz2 > 0:
# Find the maximum from lwr and the minimum
# from upr
max_lwr = max(lwr)
min_upr = min(upr)
# If the maximum element from lwr is greater
# than the minimum element from upr, swap them.
if max_lwr > min_upr:
sum1 = sum1 + (min_upr - max_lwr)
sum2 = sum2 + (max_lwr - min_upr)
lwr.remove(max_lwr)
upr.remove(min_upr)
lwr.append(min_upr)
upr.append(max_lwr)
# Output the calculated cost for the current window
if i >= (K - 1):
median = max(lwr)
print((sz1 * median - sum1) + (sum2 - median * sz2), end=" ")
# Driver Code
if __name__ == "__main__":
N, K = 8, 3
# Input array
arr = [2, 4, 3, 5, 8, 1, 2, 1]
# Call the sliding_cost function
sliding_cost(N, K, arr)
Time Complexity: O(N*logK), where N is the size of array arr[] and K is the size of window.
Auxiliary Space: O(K)
Share your thoughts in the comments
Please Login to comment...