Open In App

MEX Subarray Count

Given an array of size N, each element of the array lies between [0, N-1] i.e., the given array is a permutation. The task is to determine the number of subarrays whose MEX is greater than the Median.

Note: MEX is the smallest whole number that is not present in the array.



Examples:

Input: N=4, arr=[0, 2, 1, 3]
Output: 4
Explanation: The subarrays whose MEX is greater than Median are: [0], [0, 2], [0, 2, 1], and [0, 2, 1, 3].



Input: N=4, arr=[1, 0]
Output: 2
Explanation: The subarrays whose MEX is greater than Median are: [0], [1, 0].

MEX Subarray Count using Two Pointers:

We can firstly observe the MEX of any subarray will be in between 0 to N. So we can calculate the answer for a fixed value of MEX. Now, for a fixed value of MEX , let l be the index of left-most number 0, 1, 2, …. mex-1 and r be the index of right-most number 0, 1, 2, … mex-1. Let curr be the current length of the subarray i.e., curr=(r-l)+1. If curr is less than equal to 2*MEX, then MED of the subarray will arr[l…r] will be in between [0…..MEX-1], so number of subarrays can be calculated with some formulas. If curr greater than 2*MEX then MED of subarray will be greater.

Follow the steps to solve the problem:

Below is the implementation of above approach:




#include <bits/stdc++.h>
using namespace std;
 
int solve(vector<int> a, int N) {
    vector<int> idx(N + 2);
    vector<int> frq(N + 2, 0);
     
    // Store the indices of elements in the array
    for (int i = 0; i < N; i++) {
        idx[a[i]] = i;
    }
     
    // Base case: If the array has only one element, return 1
    if (N == 1) {
        return 1;
    }
     
    int ans = 0;    // Initialize the answer to 0
    int mex = 1;    // Initialize mex to 1
    int l = idx[0]; // Initialize l to the index of 0
    int r = idx[0]; // Initialize r to the index of 0
    frq[0] = 1;     // Mark the frequency of 0 as 1
     
    // Loop until mex reaches N
    while (mex <= N) {
        int num1 = 0, num2 = 0;
        int len = mex * 2;
        int curr = (r - l + 1);
        int op = len - curr;
 
        // Calculate num1 and num2 based on the position of mex
        if (mex == N) {
            num1 = l;
            num2 = (N - 1) - r;
        } else {
            if (idx[mex] < l) {
                num1 = (l - idx[mex]) - 1;
                num2 = (N - 1) - r;
            } else {
                num1 = l;
                num2 = (idx[mex] - r) - 1;
            }
        }
 
        // Check conditions and update the answer
        if (op == 0) {
            ans++;
        } else if (op > 0) {
            num1 = min(op, num1);
            num2 = min(op, num2);
            if (num1 > num2)
                swap(num1, num2);
            int ext = (num2 + 1) * (min((op - num2) + 1, num1 + 1));
            int rem = max(0, num1 - (op - num2));
            int m = num2;
            int x = max(0, m - rem);
            int ext1 = (m * (m + 1)) / 2;
            int ext2 = (x * (x + 1)) / 2;
            ans = ans + ext + (ext1 - ext2);
        }
 
        // Break the loop if mex reaches N
        if (mex == N)
            break;
 
        // Update l and r based on the position of mex
        if (idx[mex] < l) {
            l--;
            while (l != idx[mex]) {
                frq[a[l]] = 1;
                l--;
            }
            frq[a[l]] = 1;
        } else if (idx[mex] > r) {
            r++;
            while (r != idx[mex]) {
                frq[a[r]] = 1;
                r++;
            }
            frq[a[r]] = 1;
        }
         
        // Update mex until a non-zero frequency element is found
        while (frq[mex] != 0) {
            mex++;
        }
    }
    return ans;
}
 
// Driver Code
int main() {
    int N = 4;
    vector<int> arr = {0, 2, 1, 3};
    cout << solve(arr, N);
}




// Java Implementation:
import java.util.Arrays;
 
public class Main {
    public static void main(String[] args) {
        int N = 4;
        int[] arr = {0, 2, 1, 3};
        System.out.println(solve(arr, N));
    }
 
    public static int solve(int[] a, int N) {
        int[] idx = new int[N + 2];
        int[] frq = new int[N + 2];
 
        // Store the indices of elements in the array
        for (int i = 0; i < N; i++) {
            idx[a[i]] = i;
        }
 
        // Base case: If the array has only one element, return 1
        if (N == 1) {
            return 1;
        }
 
        int ans = 0;    // Initialize the answer to 0
        int mex = 1;    // Initialize mex to 1
        int l = idx[0]; // Initialize l to the index of 0
        int r = idx[0]; // Initialize r to the index of 0
        frq[0] = 1;     // Mark the frequency of 0 as 1
 
        // Loop until mex reaches N
        while (mex <= N) {
            int num1 = 0, num2 = 0;
            int len = mex * 2;
            int curr = (r - l + 1);
            int op = len - curr;
 
            // Calculate num1 and num2 based on the position of mex
            if (mex == N) {
                num1 = l;
                num2 = (N - 1) - r;
            } else {
                if (idx[mex] < l) {
                    num1 = (l - idx[mex]) - 1;
                    num2 = (N - 1) - r;
                } else {
                    num1 = l;
                    num2 = (idx[mex] - r) - 1;
                }
            }
 
            // Check conditions and update the answer
            if (op == 0) {
                ans++;
            } else if (op > 0) {
                num1 = Math.min(op, num1);
                num2 = Math.min(op, num2);
                if (num1 > num2)
                    swap(num1, num2);
                int ext = (num2 + 1) * (Math.min((op - num2) + 1, num1 + 1));
                int rem = Math.max(0, num1 - (op - num2));
                int m = num2;
                int x = Math.max(0, m - rem);
                int ext1 = (m * (m + 1)) / 2;
                int ext2 = (x * (x + 1)) / 2;
                ans = ans + ext + (ext1 - ext2);
            }
 
            // Break the loop if mex reaches N
            if (mex == N)
                break;
 
            // Update l and r based on the position of mex
            if (idx[mex] < l) {
                l--;
                while (l != idx[mex]) {
                    frq[a[l]] = 1;
                    l--;
                }
                frq[a[l]] = 1;
            } else if (idx[mex] > r) {
                r++;
                while (r != idx[mex]) {
                    frq[a[r]] = 1;
                    r++;
                }
                frq[a[r]] = 1;
            }
 
            // Update mex until a non-zero frequency element is found
            while (frq[mex] != 0) {
                mex++;
            }
        }
        return ans;
    }
 
    public static void swap(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
    }
}
// This code is contributed by Sakshi




def solve(a, N):
    idx = [0] * (N + 2)
    frq = [0] * (N + 2)
 
    # Store the indices of elements in the array
    for i in range(N):
        idx[a[i]] = i
 
    # Base case: If the array has only one element, return 1
    if N == 1:
        return 1
 
    ans = 0  # Initialize the answer to 0
    mex = 1  # Initialize mex to 1
    l = idx[0# Initialize l to the index of 0
    r = idx[0# Initialize r to the index of 0
    frq[0] = 1  # Mark the frequency of 0 as 1
 
    # Loop until mex reaches N
    while mex <= N:
        num1 = 0
        num2 = 0
        len = mex * 2
        curr = r - l + 1
        op = len - curr
 
        # Calculate num1 and num2 based on the position of mex
        if mex == N:
            num1 = l
            num2 = N - 1 - r
        else:
            if idx[mex] < l:
                num1 = l - idx[mex] - 1
                num2 = N - 1 - r
            else:
                num1 = l
                num2 = idx[mex] - r - 1
 
        # Check conditions and update the answer
        if op == 0:
            ans += 1
        elif op > 0:
            num1 = min(op, num1)
            num2 = min(op, num2)
            if num1 > num2:
                num1, num2 = num2, num1
            ext = (num2 + 1) * (min(op - num2 + 1, num1 + 1))
            rem = max(0, num1 - (op - num2))
            m = num2
            x = max(0, m - rem)
            ext1 = (m * (m + 1)) // 2
            ext2 = (x * (x + 1)) // 2
            ans = ans + ext + (ext1 - ext2)
 
        # Break the loop if mex reaches N
        if mex == N:
            break
 
        # Update l and r based on the position of mex
        if idx[mex] < l:
            l -= 1
            while l != idx[mex]:
                frq[a[l]] = 1
                l -= 1
            frq[a[l]] = 1
        elif idx[mex] > r:
            r += 1
            while r != idx[mex]:
                frq[a[r]] = 1
                r += 1
            frq[a[r]] = 1
 
        # Update mex until a non-zero frequency element is found
        while frq[mex] != 0:
            mex += 1
 
    return ans
 
# Driver Code
N = 4
arr = [0, 2, 1, 3]
print(solve(arr, N))




// C# program for the above approach
using System;
using System.Collections.Generic;
 
class Program
{
    static int Solve(List<int> a, int N)
    {
        List<int> idx = new List<int>(new int[N + 2]);
        List<int> frq = new List<int>(new int[N + 2]);
 
        // Store the indices of elements in the array
        for (int i = 0; i < N; i++)
        {
            idx[a[i]] = i;
        }
 
        // Base case: If the array has only one element, return 1
        if (N == 1)
        {
            return 1;
        }
 
        int ans = 0; // Initialize the answer to 0
        int mex = 1; // Initialize mex to 1
        int l = idx[0]; // Initialize l to the index of 0
        int r = idx[0]; // Initialize r to the index of 0
        frq[0] = 1;     // Mark the frequency of 0 as 1
 
        // Loop until mex reaches N
        while (mex <= N)
        {
            int num1 = 0, num2 = 0;
            int len = mex * 2;
            int curr = (r - l + 1);
            int op = len - curr;
 
            // Calculate num1 and num2 based on the position of mex
            if (mex == N)
            {
                num1 = l;
                num2 = (N - 1) - r;
            }
            else
            {
                if (idx[mex] < l)
                {
                    num1 = (l - idx[mex]) - 1;
                    num2 = (N - 1) - r;
                }
                else
                {
                    num1 = l;
                    num2 = (idx[mex] - r) - 1;
                }
            }
 
            // Check conditions and update the answer
            if (op == 0)
            {
                ans++;
            }
            else if (op > 0)
            {
                num1 = Math.Min(op, num1);
                num2 = Math.Min(op, num2);
                if (num1 > num2)
                    Swap(ref num1, ref num2);
                int ext = (num2 + 1) * (Math.Min((op - num2) + 1, num1 + 1));
                int rem = Math.Max(0, num1 - (op - num2));
                int m = num2;
                int x = Math.Max(0, m - rem);
                int ext1 = (m * (m + 1)) / 2;
                int ext2 = (x * (x + 1)) / 2;
                ans = ans + ext + (ext1 - ext2);
            }
 
            // Break the loop if mex reaches N
            if (mex == N)
                break;
 
            // Update l and r based on the position of mex
            if (idx[mex] < l)
            {
                l--;
                while (l != idx[mex])
                {
                    frq[a[l]] = 1;
                    l--;
                }
                frq[a[l]] = 1;
            }
            else if (idx[mex] > r)
            {
                r++;
                while (r != idx[mex])
                {
                    frq[a[r]] = 1;
                    r++;
                }
                frq[a[r]] = 1;
            }
 
            // Update mex until a non-zero frequency element is found
            while (frq[mex] != 0)
            {
                mex++;
            }
        }
        return ans;
    }
 
    // Helper method to swap two integers
    static void Swap(ref int a, ref int b)
    {
        int temp = a;
        a = b;
        b = temp;
    }
 
    // Driver Code
    static void Main()
    {
        int N = 4;
        List<int> arr = new List<int> { 0, 2, 1, 3 };
        Console.WriteLine(Solve(arr, N));
    }
}
 
// This code is contributed by Susobhan Akhuli




// JavaScript code for the above aprpoach:
 
function solve(a, N) {
    let idx = new Array(N + 2).fill(0);
    let frq = new Array(N + 2).fill(0);
 
    // Store the indices of elements in the array
    for (let i = 0; i < N; i++) {
        idx[a[i]] = i;
    }
 
    // Base case: If the array has only one element, return 1
    if (N === 1) {
        return 1;
    }
 
    let ans = 0; // Initialize the answer to 0
    let mex = 1; // Initialize mex to 1
    let l = idx[0]; // Initialize l to the index of 0
    let r = idx[0]; // Initialize r to the index of 0
    frq[0] = 1; // Mark the frequency of 0 as 1
 
    // Loop until mex reaches N
    while (mex <= N) {
        let num1 = 0, num2 = 0;
        let len = mex * 2;
        let curr = r - l + 1;
        let op = len - curr;
 
        // Calculate num1 and num2 based on the position of mex
        if (mex === N) {
            num1 = l;
            num2 = (N - 1) - r;
        }
        else {
            if (idx[mex] < l) {
                num1 = (l - idx[mex]) - 1;
                num2 = (N - 1) - r;
            }
            else {
                num1 = l;
                num2 = (idx[mex] - r) - 1;
            }
        }
 
        // Check conditions and update the answer
        if (op === 0) {
            ans++;
        }
        else if (op > 0) {
            num1 = Math.min(op, num1);
            num2 = Math.min(op, num2);
            if (num1 > num2) {
                [num1, num2] = [num2, num1];
            }
            let ext = (num2 + 1) * Math.min((op - num2) + 1, num1 + 1);
            let rem = Math.max(0, num1 - (op - num2));
            let m = num2;
            let x = Math.max(0, m - rem);
            let ext1 = (m * (m + 1)) / 2;
            let ext2 = (x * (x + 1)) / 2;
            ans = ans + ext + (ext1 - ext2);
        }
 
        // Break the loop if mex reaches N
        if (mex === N) {
            break;
        }
 
        // Update l and r based on the position of mex
        if (idx[mex] < l) {
            l--;
            while (l !== idx[mex]) {
                frq[a[l]] = 1;
                l--;
            }
            frq[a[l]] = 1;
        }
        else if (idx[mex] > r) {
            r++;
            while (r !== idx[mex]) {
                frq[a[r]] = 1;
                r++;
            }
            frq[a[r]] = 1;
        }
 
        // Update mex until a non-zero frequency element is found
        while (frq[mex] !== 0) {
            mex++;
        }
    }
    return ans;
}
 
// Driver Code
let N = 4;
let arr = [0, 2, 1, 3];
console.log(solve(arr, N));

Output
4








Time Complexity: O(N)
Auxiliary Space: O(N)


Article Tags :