# Queries to calculate average of an array after removing K smallest and largest elements with updates

• Last Updated : 18 Jun, 2021

Given two positive integers N and K, initialize an empty array arr[] and Q number of queries of the following two types:

The task is to process the given queries and print the results accordingly.

Examples:

Input: N = 3, K = 1, Q = 5, Queries[] = { addInteger(4), addInteger(2), calculateSpecialAverage(), addInteger(10), calculateSpecialAverage() }
Output: -1, 4
Explanation:
Below are the queries performed:
Query 1 is to insert element 4 in the array, arr[] becomes {4}.
Query 2 is to insert the element 2 in the array, arr[] becomes {4, 2}.
Query 3 is to find the average. Since the size of the array is less than N(= 3), print -1.
Query 4 is to insert the element 10 in the array, arr[] becomes {4, 2, 10}.
Query 5 is to find the average. Since the size of the array =3, remove K(= 1) the smallest element i.e., 2 and then remove the largest element i.e., 10. Now the average will be 4/1 = 4.

Input: N = 3, K = 1, Q = 5, Queries[] = { addInteger(4), addInteger(21), calculateSpecialAverage() }
Output: -1

Approach: The given problem can be solved by using the multiset. Follow the steps below to solve the problem:

• Initialize three multisets left, right and mid to store K smallest, K largest, and the remaining (N – 2*K) integers.
• Declare a vector v of size N to store the last N integers.
• Declare an integer variable pos to keep track of the current index and an integer sum to store the sum of values in the mid multiset, which is the desired sum for calculating the average of (N – 2*K) integers.
• Define a function add to insert an integer in left, mid, or right multiset based on its value. To insert integer in the correct multiset follow the following steps:
• Initially, insert the integer in the left multiset.
• If the size of the left multiset exceeds k, delete the largest integer from the left multiset and insert it in the mid multiset.
• If the size of mid multiset exceeds (n – 2*k), delete the largest integer from mid multiset and insert it in the right multiset.
• While removing and adding integers in mid multiset maintain the correct value of sum i.e. if an integer is removed from mid multiset subtract its value from the sum and similarly if an integer is added in the mid multiset, add its value to sum, to keep the value of sum updated.
• Declare a function remove to erase the integers from left, right, or mid multiset.
• If the value of the integer num is less than or equal to the largest integer in the left multiset, then find and erase the integer from the left multiset, otherwise search for it in mid or right multiset, based on its value.
• If after the removal of num, the size of the left multiset decreases, delete the smallest integer from the mid multiset and insert it in the left multiset.
• Similarly, for mid multiset, if the size decreases, delete the smallest integer from the right multiset and insert it in the mid multiset.
• Define a function addInteger to add an integer to the current stream:
• If the number of integers in the current stream(sum of the size of left, mid, right multiset) exceeds n, remove the integer at index pos%n.
• Call the function add to insert the integer in the left, mid, or right multiset, based on its value.
• Define the function calculateSpecialAverage to return the special average:
• If the number of integers in the stream is less than N, then print -1.
• Otherwise, print the average as (sum/(N – 2*K)).

Below is the implementation of the above approach:

## C++

 `// C++ program for the above approach`` ` `#include ``using` `namespace` `std;`` ` `// Special Average class``class` `SpecialAverage {``public``:``    ``// Three multisets to store the``    ``// smaller K larger K and the``    ``// remaining (n-2*k) integers``    ``multiset<``int``> left, mid, right;`` ` `    ``int` `n, k;`` ` `    ``// Stores the index of current``    ``// integer in running stream of``    ``// integers and the sum of integers``    ``// in mid multiset``    ``long` `pos, sum;`` ` `    ``// Array to store last n integers``    ``vector<``int``> v;`` ` `    ``// Constructor to initialize the``    ``// values of n and k and initialize``    ``// default values``    ``SpecialAverage(``int` `nvalue, ``int` `kvalue)``    ``{``        ``n = nvalue;``        ``k = kvalue;``        ``pos = 0;``        ``sum = 0;``        ``for` `(``int` `i = 0; i < n; i++)``            ``v.push_back(0);``    ``}`` ` `    ``// Add current integer in the``    ``// multiset left, mid or right``    ``// based on its value``    ``void` `add(``int` `num)``    ``{``        ``// Firstly, insert num in the``        ``// left multiset``        ``left.insert(num);`` ` `        ``// Check if size of the left``        ``// multiset is greater than k``        ``if` `(left.size() > k) {`` ` `            ``// Stores the value of the``            ``// largest integer in the``            ``// left multiset``            ``int` `temp = *(prev(end(left)));`` ` `            ``// Insert temp in the``            ``// mid multiset``            ``mid.insert(temp);`` ` `            ``// Remove temp from the``            ``// left multiset``            ``left.erase(prev(end(left)));`` ` `            ``// Add the value of temp``            ``// to the current sum``            ``sum += temp;``        ``}`` ` `        ``// Check if the size of mid``        ``// multiset exceeds (n-2*k)``        ``if` `(mid.size() > (n - 2 * k)) {`` ` `            ``// Stores the value of the``            ``// largest integer in the``            ``// mid multiset``            ``int` `temp = *(prev(end(mid)));`` ` `            ``// Insert temp in the``            ``// right multiset``            ``right.insert(temp);`` ` `            ``// Remove temp from the``            ``// mid multiset``            ``mid.erase(prev(end(mid)));`` ` `            ``// Subtract the value of``            ``// temp from current sum``            ``sum -= temp;``        ``}``    ``}`` ` `    ``// Remove integer from the``    ``// multiset left, mid or right``    ``// based on its value``    ``void` `remove``(``int` `ele)``    ``{`` ` `        ``// If integer exists in the``        ``// left multiset``        ``if` `(ele <= *(left.rbegin()))``            ``left.erase(left.find(ele));`` ` `        ``// If integer exists in the``        ``// mid multiset``        ``else` `if` `(ele <= *(mid.rbegin())) {`` ` `            ``// Subtract the value of``            ``// integer from current sum``            ``sum -= ele;``            ``mid.erase(mid.find(ele));``        ``}`` ` `        ``// If integer exists in the``        ``// right multiset``        ``else``            ``right.erase(right.find(ele));`` ` `        ``// Balance all the multisets``        ``// left, right and mid check``        ``// if size of the left multiset``        ``// is less than k``        ``if` `(left.size() < k) {`` ` `            ``// Stores the value of``            ``// smallest integer``            ``// in mid multiset``            ``int` `temp = *(mid.begin());`` ` `            ``// Insert temp in the``            ``// left multiset``            ``left.insert(temp);`` ` `            ``// Remove temp from the``            ``// mid multiset``            ``mid.erase(mid.begin());`` ` `            ``// Subtract the value of``            ``// temp from current sum``            ``sum -= temp;``        ``}`` ` `        ``// Check if the size of mid``        ``// multiset becomes lesser``        ``// than (n-2*k)``        ``if` `(mid.size() < (n - 2 * k)) {`` ` `            ``// Stores the value of``            ``// smallest integer in``            ``// right multiset``            ``int` `temp = *(right.begin());`` ` `            ``// Insert temp in the``            ``// mid multiset``            ``mid.insert(temp);`` ` `            ``// Remove temp from the``            ``// right multiset``            ``right.erase(right.begin());`` ` `            ``// Add the value of temp``            ``// to the current sum``            ``sum += temp;``        ``}``    ``}`` ` `    ``// Function to add integer to``    ``// the current stream``    ``void` `addInteger(``int` `num)``    ``{`` ` `        ``// Check if the total number``        ``// of elements in stream > n``        ``if` `(pos >= n)`` ` `            ``// Call the function to``            ``// remove  extra integer``            ``remove``(v[pos % n]);`` ` `        ``// Insert the current integer``        ``// in the array v``        ``v[(pos++) % n] = num;`` ` `        ``// Call the function to add``        ``// the current integer in left,``        ``// mid or right multiset``        ``// based on its value``        ``add(num);``    ``}`` ` `    ``// Function to calculate the``    ``// special average``    ``int` `calculateSpecialAverage()``    ``{``        ``// Check if the total number``        ``// of elements is greater than``        ``// or equal to n``        ``if` `(pos >= n)`` ` `            ``// Return desired average``            ``return` `((``double``)sum) / (n - 2 * k);``        ``return` `-1;``    ``}``};`` ` `// Function to process all the queries``void` `processQueries(``int` `n, ``int` `k)``{``    ``// Create an object of the class``    ``SpecialAverage* avg``        ``= ``new` `SpecialAverage(n, k);`` ` `    ``// Add integer Query``    ``avg->addInteger(4);``    ``avg->addInteger(2);`` ` `    ``// Find average Query``    ``cout << avg->calculateSpecialAverage()``         ``<< endl;`` ` `    ``// Add integer Query``    ``avg->addInteger(10);`` ` `    ``// Find average Query``    ``cout << avg->calculateSpecialAverage()``         ``<< endl;``}`` ` `// Driver Code``int` `main()``{``    ``int` `N = 3, K = 1;``    ``processQueries(N, K);`` ` `    ``return` `0;``}`

Output:

```-1
4
```

Time Complexity: O(log N) for addInteger() and O(1) for calculateSpecialAverage()
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up