Open In App

CSES Solutions – Sliding Window Cost

Last Updated : 16 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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)


Output

2 2 5 7 7 1

Time Complexity: O(N*logK), where N is the size of array arr[] and K is the size of window.
Auxiliary Space: O(K)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads