# Queries to replace subarrays by equal length arrays with at most P replacements allowed for any array element

• Difficulty Level : Medium
• Last Updated : 04 Mar, 2021

Given an array, arr[] of size N, an integer P and a 2D array Q[][] consisting of queries of the following type:

• 1 L R B[R – L + 1]: The task for this query is to replace the subarray {arr[L], … arr[R] with the array B[] b given that any array element can be replaced at most P times.
• 2 X: The task for this query is to print arr[X].

Examples:

Input: arr[] = {3, 10, 4, 2, 8, 7}, P = 1, Q[][] = {{1, 0, 3, 3, 2, 1, 11}, {2, 3}, {1, 2, 3, 5, 7}, {2, 2} }
Output: 11 1
Explanation:
Query 1: Replacing the subarray {arr, …, arr} with the array {3, 2, 1, 11} modifies arr[] to {3, 2, 1, 11, 8, 7}
Query 2: Print arr.
Query 3: Since P = 1, therefore the subarray {arr, …, arr} can’t be replaced more than once.
Query 4: Print arr.

Input: arr[] = {1, 2, 3, 4, 5}, P = 2, Q[][] = {{2, 0}, {1, 1, 3, 6, 7, 8}, {1, 3, 4, 10, 12}, {2, 4}}
Output: 1 12

Approach: The problem can be solved using the Union-Find algorithm. The idea is to traverse the array Q[][] and check if Q is equal to 1 or not. If found to be true, then replace the subarray with the new array and whenever any array element has been replaced P times, then create a new subset using the union-find. Follow the steps below to solve the problem:

• Initialize an array, say visited[], where visited[i] check index i is present in any disjoint subset or not.
• Initialize an array, say count[], where count[i] stores how many times arr[i] has been replaced.
• Initialize an array, say last[], to store the largest element of each disjoint subset.
• Initialize an array, say parent[], to store the smallest element of each disjoint subset.
• Traverse the Q[][] array and for each query check if Q[i] == 1 or not. If found to be true then perform the following operations:
• Iterate over the range [ Q[i], Q[i] ] using variable low and check if visited[low] is true or not. If found to be true then find the parent of that subset where low present, find the largest element present in the subset.
• Otherwise, check if count[low] is less than P or not. If found to be true then replace the value of arr[low] with the corresponding value.
• Otherwise, check if count[low] is equal to P or not. If found to be true then create a new disjoint subset of the current index.
• Otherwise, print arr[Q[i]]].

Below is the implementation of the above approach:

## Java

 `// Java program to implement``// the above approach` `import` `java.io.*;``import` `java.util.*;` `class` `GFG {` `    ``// visited[i]: Check index i is present``    ``// in any disjoint subset or not.``    ``static` `boolean``[] visited;` `    ``// Store the smallest element``    ``// of each disjoint subset``    ``static` `int``[] parent;` `    ``// count[i]: Stores the count``    ``// of replacements of arr[i]``    ``static` `int``[] last;` `    ``// Store the largest element``    ``// of each disjoint subset``    ``static` `int``[] count;` `    ``// Function to process all the given Queries``    ``static` `void` `processQueries(``int``[] arr, ``int` `P,``                               ``List > Q)``    ``{``        ``// Traverse the queries[][] array``        ``for` `(``int` `i = ``0``; i < Q.size(); i++) {` `            ``// Stores the current query``            ``List query = Q.get(i);` `            ``// If query of type is 1``            ``if` `(query.get(``0``) == ``1``) {` `                ``// Perform the query of type 1``                ``processTypeOneQuery(query, arr, P);``            ``}` `            ``// If query of type is 2``            ``else` `{` `                ``// Stores 2nd element of``                ``// current query``                ``int` `index = query.get(``1``);` `                ``// Print arr[index]``                ``System.out.println(arr[index]);``            ``}``        ``}``    ``}` `    ``// Function to perform the query of type 1``    ``static` `void` `processTypeOneQuery(``        ``List query, ``int``[] arr, ``int` `P)``    ``{``        ``// Stores the value of L``        ``int` `low = query.get(``1``);` `        ``// Stores the value of R``        ``int` `high = query.get(``2``);` `        ``// Stores leftmost index of the``        ``// subarray for which a new``        ``// subset can be generated``        ``int` `left = -``1``;` `        ``// Stores index of``        ``// the query[] array``        ``int` `j = ``3``;` `        ``// Iterate over the``        ``// range [low, high]``        ``while` `(low <= high) {` `            ``// If low is present in``            ``// any of the subset``            ``if` `(visited[low]) {` `                ``// If no subset created for``                ``// the subarray arr[left...low - 1]``                ``if` `(left != -``1``) {` `                    ``// Create a new subset``                    ``newUnion(left, low - ``1``,``                             ``arr.length);` `                    ``// Update left``                    ``left = -``1``;``                ``}` `                ``// Stores next index to be``                ``// processed``                ``int` `jump = findJumpLength(low);` `                ``// Update low``                ``low += jump;` `                ``// Update j``                ``j += jump;``            ``}` `            ``// If arr[low] has been``            ``// already replaced P times``            ``else` `if` `(count[low] == P) {` `                ``// If already subset``                ``// created for left``                ``if` `(left == -``1``) {` `                    ``// Update left``                    ``left = low;``                ``}` `                ``// Mark low as an element``                ``// of any subset``                ``visited[low] = ``true``;` `                ``// Update low``                ``low++;` `                ``// Update j``                ``j++;``            ``}` `            ``// If arr[low] has been replaced``            ``// less than P times``            ``else` `{` `                ``// If no subset created for``                ``// the subarray arr[left...low - 1]``                ``if` `(left != -``1``) {` `                    ``// Create a new subset``                    ``newUnion(left, low - ``1``, arr.length);` `                    ``// Update left``                    ``left = -``1``;``                ``}` `                ``// Replace arr[low] with``                ``// the corresponding value``                ``arr[low] = query.get(j);` `                ``// Update count[low]``                ``count[low]++;` `                ``// Update low``                ``low++;` `                ``// Update j``                ``j++;``            ``}``        ``}` `        ``// If no subset has been created for``        ``// the subarray arr[left...low - 1]``        ``if` `(left != -``1``) {` `            ``// Create a new subset``            ``newUnion(left, high, arr.length);``        ``}``    ``}` `    ``// Function to find the next index``    ``// to be processed after visiting low``    ``static` `int` `findJumpLength(``int` `low)``    ``{` `        ``// Stores smallest index of``        ``// the subset where low present``        ``int` `p = findParent(low);` `        ``// Stores next index``        ``// to be processed``        ``int` `nextIndex = last[p] + ``1``;` `        ``// Stores difference between``        ``// low and nextIndex``        ``int` `jump = (nextIndex - low);` `        ``// Return jump``        ``return` `jump;``    ``}` `    ``// Function to create a new subset``    ``static` `void` `newUnion(``int` `low, ``int` `high,``                         ``int` `N)``    ``{` `        ``// Iterate over``        ``// the range [low + 1, high]``        ``for` `(``int` `i = low + ``1``; i <= high;``             ``i++) {` `            ``// Perform union operation``            ``// on low``            ``union(low, i);``        ``}` `        ``// If just smaller element of low``        ``// is present in any of the subset``        ``if` `(low > ``0` `&& visited[low - ``1``]) {` `            ``// Perform union on (low - 1)``            ``union(low - ``1``, low);``        ``}` `        ``// If just greater element of high``        ``// is present in any of the subset``        ``if` `(high < N - ``1` `&& visited[high + ``1``]) {` `            ``// Perform union on high``            ``union(high, high + ``1``);``        ``}``    ``}` `    ``// Function to find the smallest``    ``// element of the subset``    ``static` `int` `findParent(``int` `u)``    ``{` `        ``// Base Case``        ``if` `(parent[u] == u)``            ``return` `u;` `        ``// Stores smallest element``        ``// of parent[u``        ``return` `parent[u]``            ``= findParent(parent[u]);``    ``}` `    ``// Function to perform union operation``    ``static` `void` `union(``int` `u, ``int` `v)``    ``{``        ``// Stores smallest element``        ``// of subset containing u``        ``int` `p1 = findParent(u);` `        ``// Stores smallest element``        ``// of subset containing u``        ``int` `p2 = findParent(v);` `        ``// Update parent[p2]``        ``parent[p2] = p1;` `        ``// Update last[p1]``        ``last[p1] = last[p2];``    ``}` `    ``// Function to find all the queries``    ``static` `List > getQueries()``    ``{` `        ``// Stores all the queries``        ``List > Q``            ``= ``new` `ArrayList >();` `        ``// Initialize all queries``        ``Integer[] query1 = { ``1``, ``0``, ``3``, ``3``, ``2``,``                             ``1``, ``11` `};``        ``Integer[] query2 = { ``2``, ``3` `};``        ``Integer[] query3 = { ``1``, ``2``, ``3``, ``5``, ``7` `};``        ``Integer[] query4 = { ``2``, ``2` `};` `        ``// Insert all queries``        ``Q.add(Arrays.asList(query1));``        ``Q.add(Arrays.asList(query2));``        ``Q.add(Arrays.asList(query3));``        ``Q.add(Arrays.asList(query4));` `        ``// Return all queries``        ``return` `Q;``    ``}` `    ``// Driver Code``    ``public` `static` `void` `main(String[] args)``    ``{` `        ``int``[] arr = { ``3``, ``10``, ``4``, ``2``, ``8``, ``7` `};``        ``int` `N = arr.length;``        ``int` `P = ``1``;` `        ``parent = ``new` `int``[N];``        ``last = ``new` `int``[N];``        ``count = ``new` `int``[N];``        ``visited = ``new` `boolean``[N];` `        ``// Initialize parent[] and``        ``// last[] array``        ``for` `(``int` `i = ``0``; i < parent.length;``             ``i++) {` `            ``// Update parent[i]``            ``parent[i] = i;` `            ``// Update last[i]``            ``last[i] = i;``        ``}` `        ``List > Q = getQueries();``        ``processQueries(arr, P, Q);``    ``}``}`

## Python3

 `# Python3 program to implement``# the above approach` `# visited[i]: Check index i is present``# in any disjoint subset or not.``visited ``=` `[]` `# Store the smallest element``# of each disjoint subset``parent ``=` `[]` `# count[i]: Stores the count``# of replacements of arr[i]``last ``=` `[]` `# Store the largest element``# of each disjoint subset``count ``=` `[]` `# Function to process all the given Queries``def` `processQueries(arr, P, Q):``  ` `    ``# Traverse the [,]queries array``    ``for` `i ``in` `range``(``len``(Q)):``    ` `        ``# Stores the current query``        ``query ``=` `Q[i];` `        ``# If query of type is 1``        ``if` `(query[``0``] ``=``=` `1``):``          ` `            ``# Perform the query of type 1``            ``processTypeOneQuery(query, arr, P);``        ` `        ``# If query of type is 2``        ``else``:``          ` `            ``# Stores 2nd element of``            ``# current query``            ``index ``=` `query[``1``];``            ` `            ``# Print arr[index]``            ``print``(arr[index]);``        ` `# Function to perform the query of type 1``def` `processTypeOneQuery(query, arr, P):` `    ``# Stores the value of L``    ``low ``=` `query[``1``];` `    ``# Stores the value of R``    ``high ``=` `query[``2``];` `    ``# Stores leftmost index of the``    ``# subarray for which a new``    ``# subset can be generated``    ``left ``=` `-``1``;``    ` `    ``# Stores index of``    ``# the query[] array``    ``j ``=` `3``;``    ` `    ``# Iterate over the``    ``# range [low, high]``    ``while` `(low <``=` `high):``      ` `        ``# If low is present in``        ``# any of the subset``        ``if` `(visited[low]):``          ` `            ``# If no subset created for``            ``# the subarray arr[left...low - 1]``            ``if` `(left !``=` `-``1``):``              ` `                ``# Create a new subset``                ``newUnion(left, low ``-` `1``,``len``(arr));``                ` `                ``# Update left``                ``left ``=` `-``1``;``            ` `            ``# Stores next index to be``            ``# processed``            ``jump ``=` `findJumpLength(low);``            ` `            ``# Update low``            ``low ``+``=` `jump;``            ` `            ``# Update j``            ``j ``+``=` `jump;``        ` `        ``# If arr[low] has been``        ``# already replaced P times``        ``elif` `(count[low] ``=``=` `P):``          ` `            ``# If already subset``            ``# created for left``            ``if` `(left ``=``=` `-``1``):``              ` `                ``# Update left``                ``left ``=` `low;``            ` `            ``# Mark low as an element``            ``# of any subset``            ``visited[low] ``=` `True``;``            ` `            ``# Update low``            ``low ``+``=` `1``            ` `            ``# Update j``            ``j ``+``=` `1``        ` `        ``# If arr[low] has been replaced``        ``# less than P times``        ``else``:``          ` `            ``# If no subset created for``            ``# the subarray arr[left...low - 1]``            ``if` `(left !``=` `-``1``):``              ` `                ``# Create a new subset``                ``newUnion(left, low ``-` `1``, ``len``(arr));``                ` `                ``# Update left``                ``left ``=` `-``1``;``            ` `            ``# Replace arr[low] with``            ``# the corresponding value``            ``arr[low] ``=` `query[j];``            ` `            ``# Update count[low]``            ``count[low] ``+``=` `1``            ` `            ``# Update low``            ``low ``+``=` `1``            ` `            ``# Update j``            ``j ``+``=` `1``        ` `    ``# If no subset has been created for``    ``# the subarray arr[left...low - 1]``    ``if` `(left !``=` `-``1``):``      ` `        ``# Create a new subset``        ``newUnion(left, high, ``len``(arr));``    ` `# Function to find the next index``# to be processed after visiting low``def` `findJumpLength(low):` `    ``# Stores smallest index of``    ``# the subset where low present``    ``p ``=` `findParent(low);` `    ``# Stores next index``    ``# to be processed``    ``nextIndex ``=` `last[p] ``+` `1``;``    ` `    ``# Stores difference between``    ``# low and nextIndex``    ``jump ``=` `(nextIndex ``-` `low);``    ` `    ``# Return jump``    ``return` `jump;` `# Function to create a new subset``def` `newUnion(low, high,N):` `    ``# Iterate over``    ``# the range [low + 1, high]``    ``for` `i ``in` `range``(low``+``1``,high``+``1``):``    ` `        ``# Perform union operation``        ``# on low``        ``union(low, i);``    ` `    ``# If just smaller element of low``    ``# is present in any of the subset``    ``if` `(low > ``0` `and` `visited[low ``-` `1``]):``      ` `        ``# Perform union on (low - 1)``        ``union(low ``-` `1``, low);``    ` `    ``# If just greater element of high``    ``# is present in any of the subset``    ``if` `(high < N ``-` `1` `and` `visited[high ``+` `1``]):``      ` `        ``# Perform union on high``        ``union(high, high ``+` `1``);``    ` `# Function to find the smallest``# element of the subset``def` `findParent(u):` `    ``# Base Case``    ``if` `(parent[u] ``=``=` `u):``        ``return` `u;``      ` `    ``# Stores smallest element``    ``# of parent[u``    ``parent[u]``=` `findParent(parent[u]);``    ``return` `parent[u]` `# Function to perform union operation``def` `union(u, v):` `    ``# Stores smallest element``    ``# of subset containing u``    ``p1 ``=` `findParent(u);``    ` `    ``# Stores smallest element``    ``# of subset containing u``    ``p2 ``=` `findParent(v);``    ` `    ``# Update parent[p2]``    ``parent[p2] ``=` `p1;``    ` `    ``# Update last[p1]``    ``last[p1] ``=` `last[p2];` `# Function to find all the queries``def` `getQueries():` `    ``# Stores all the queries``    ``Q ``=` `[]``        ` `    ``# Initialize all queries``    ``query1 ``=` `[ ``1``, ``0``, ``3``, ``3``, ``2``,``1``, ``11` `]``    ``query2 ``=` `[ ``2``, ``3` `]``    ``query3 ``=` `[ ``1``, ``2``, ``3``, ``5``, ``7` `]``    ``query4 ``=` `[ ``2``, ``2` `]``    ` `    ``# Insert all queries        ``    ``Q.append(query1)``    ``Q.append(query2)``    ``Q.append(query3)``    ``Q.append(query4)``    ` `    ``# Return all queries``    ``return` `Q;` `# Driver Code``if` `__name__``=``=``'__main__'``:` `    ``arr ``=` `[ ``3``, ``10``, ``4``, ``2``, ``8``, ``7` `]``    ``N ``=` `len``(arr)``    ``P ``=` `1``;``    ``parent ``=` `[i ``for` `i ``in` `range``(N)]``    ``last ``=` `[i ``for` `i ``in` `range``(N)]``    ``count ``=` `[``0` `for` `i ``in` `range``(N)]``    ``visited ``=` `[``False` `for` `i ``in` `range``(N)]``    ` `    ``Q ``=` `getQueries();``    ``processQueries(arr, P, Q);` `    ``# This code is contributed by rutvik_56.`

## C#

 `// C# program to implement``// the above approach``using` `System;``using` `System.Collections.Generic;` `public` `class` `GFG {` `    ``// visited[i]: Check index i is present``    ``// in any disjoint subset or not.``    ``static` `bool``[] visited;` `    ``// Store the smallest element``    ``// of each disjoint subset``    ``static` `int``[] parent;` `    ``// count[i]: Stores the count``    ``// of replacements of arr[i]``    ``static` `int``[] last;` `    ``// Store the largest element``    ``// of each disjoint subset``    ``static` `int``[] count;` `    ``// Function to process all the given Queries``    ``static` `void` `processQueries(``int``[] arr, ``int` `P,``                               ``List > Q)``    ``{``      ` `        ``// Traverse the [,]queries array``        ``for` `(``int` `i = 0; i < Q.Count; i++) {` `            ``// Stores the current query``            ``List<``int``> query = Q[i];` `            ``// If query of type is 1``            ``if` `(query == 1) {` `                ``// Perform the query of type 1``                ``processTypeOneQuery(query, arr, P);``            ``}` `            ``// If query of type is 2``            ``else` `{` `                ``// Stores 2nd element of``                ``// current query``                ``int` `index = query;` `                ``// Print arr[index]``                ``Console.WriteLine(arr[index]);``            ``}``        ``}``    ``}` `    ``// Function to perform the query of type 1``    ``static` `void` `processTypeOneQuery(``        ``List<``int``> query, ``int``[] arr, ``int` `P)``    ``{``        ``// Stores the value of L``        ``int` `low = query;` `        ``// Stores the value of R``        ``int` `high = query;` `        ``// Stores leftmost index of the``        ``// subarray for which a new``        ``// subset can be generated``        ``int` `left = -1;` `        ``// Stores index of``        ``// the query[] array``        ``int` `j = 3;` `        ``// Iterate over the``        ``// range [low, high]``        ``while` `(low <= high) {` `            ``// If low is present in``            ``// any of the subset``            ``if` `(visited[low]) {` `                ``// If no subset created for``                ``// the subarray arr[left...low - 1]``                ``if` `(left != -1) {` `                    ``// Create a new subset``                    ``newUnion(left, low - 1,``                             ``arr.Length);` `                    ``// Update left``                    ``left = -1;``                ``}` `                ``// Stores next index to be``                ``// processed``                ``int` `jump = findJumpLength(low);` `                ``// Update low``                ``low += jump;` `                ``// Update j``                ``j += jump;``            ``}` `            ``// If arr[low] has been``            ``// already replaced P times``            ``else` `if` `(count[low] == P) {` `                ``// If already subset``                ``// created for left``                ``if` `(left == -1) {` `                    ``// Update left``                    ``left = low;``                ``}` `                ``// Mark low as an element``                ``// of any subset``                ``visited[low] = ``true``;` `                ``// Update low``                ``low++;` `                ``// Update j``                ``j++;``            ``}` `            ``// If arr[low] has been replaced``            ``// less than P times``            ``else` `{` `                ``// If no subset created for``                ``// the subarray arr[left...low - 1]``                ``if` `(left != -1) {` `                    ``// Create a new subset``                    ``newUnion(left, low - 1, arr.Length);` `                    ``// Update left``                    ``left = -1;``                ``}` `                ``// Replace arr[low] with``                ``// the corresponding value``                ``arr[low] = query[j];` `                ``// Update count[low]``                ``count[low]++;` `                ``// Update low``                ``low++;` `                ``// Update j``                ``j++;``            ``}``        ``}` `        ``// If no subset has been created for``        ``// the subarray arr[left...low - 1]``        ``if` `(left != -1) {` `            ``// Create a new subset``            ``newUnion(left, high, arr.Length);``        ``}``    ``}` `    ``// Function to find the next index``    ``// to be processed after visiting low``    ``static` `int` `findJumpLength(``int` `low)``    ``{` `        ``// Stores smallest index of``        ``// the subset where low present``        ``int` `p = findParent(low);` `        ``// Stores next index``        ``// to be processed``        ``int` `nextIndex = last[p] + 1;` `        ``// Stores difference between``        ``// low and nextIndex``        ``int` `jump = (nextIndex - low);` `        ``// Return jump``        ``return` `jump;``    ``}` `    ``// Function to create a new subset``    ``static` `void` `newUnion(``int` `low, ``int` `high,``                         ``int` `N)``    ``{` `        ``// Iterate over``        ``// the range [low + 1, high]``        ``for` `(``int` `i = low + 1; i <= high;``             ``i++) {` `            ``// Perform union operation``            ``// on low``            ``union(low, i);``        ``}` `        ``// If just smaller element of low``        ``// is present in any of the subset``        ``if` `(low > 0 && visited[low - 1]) {` `            ``// Perform union on (low - 1)``            ``union(low - 1, low);``        ``}` `        ``// If just greater element of high``        ``// is present in any of the subset``        ``if` `(high < N - 1 && visited[high + 1]) {` `            ``// Perform union on high``            ``union(high, high + 1);``        ``}``    ``}` `    ``// Function to find the smallest``    ``// element of the subset``    ``static` `int` `findParent(``int` `u)``    ``{` `        ``// Base Case``        ``if` `(parent[u] == u)``            ``return` `u;` `        ``// Stores smallest element``        ``// of parent[u``        ``return` `parent[u]``            ``= findParent(parent[u]);``    ``}` `    ``// Function to perform union operation``    ``static` `void` `union(``int` `u, ``int` `v)``    ``{``        ``// Stores smallest element``        ``// of subset containing u``        ``int` `p1 = findParent(u);` `        ``// Stores smallest element``        ``// of subset containing u``        ``int` `p2 = findParent(v);` `        ``// Update parent[p2]``        ``parent[p2] = p1;` `        ``// Update last[p1]``        ``last[p1] = last[p2];``    ``}` `    ``// Function to find all the queries``    ``static` `List > getQueries()``    ``{` `        ``// Stores all the queries``        ``List > Q``            ``= ``new` `List >();` `        ``// Initialize all queries``        ``int``[] query1 = { 1, 0, 3, 3, 2,``                             ``1, 11 };``        ``int``[] query2 = { 2, 3 };``        ``int``[] query3 = { 1, 2, 3, 5, 7 };``        ``int``[] query4 = { 2, 2 };` `        ``// Insert all queries        ``        ``Q.Add(``new` `List<``int``>(query1));``        ``Q.Add(``new` `List<``int``>(query2));``        ``Q.Add(``new` `List<``int``>(query3));``        ``Q.Add(``new` `List<``int``>(query4));` `        ``// Return all queries``        ``return` `Q;``    ``}` `    ``// Driver Code``    ``public` `static` `void` `Main(String[] args)``    ``{` `        ``int``[] arr = { 3, 10, 4, 2, 8, 7 };``        ``int` `N = arr.Length;``        ``int` `P = 1;` `        ``parent = ``new` `int``[N];``        ``last = ``new` `int``[N];``        ``count = ``new` `int``[N];``        ``visited = ``new` `bool``[N];` `        ``// Initialize parent[] and``        ``// last[] array``        ``for` `(``int` `i = 0; i < parent.Length;``             ``i++) {` `            ``// Update parent[i]``            ``parent[i] = i;` `            ``// Update last[i]``            ``last[i] = i;``        ``}` `        ``List > Q = getQueries();``        ``processQueries(arr, P, Q);``    ``}``}` `// This code is contributed by Amit Katiyar`

Output:

```11
1```

Time Complexity: O(N + |Q| * P)
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up