Open In App

Count ways to make given Subarray strictly increasing by replacing one element for Q queries

Given a strictly increasing array A[] of size N, an integer K and Q queries of type [L, R], the task is to count the number of ways such that the subarray from L to R remains strictly increasing when only one replacement is performed and all the elements will be in the range [1, K].

Examples: 



Input: A[] = {1, 2, 4, 5}, K = 5, Q = 2, Queries[][] = {{1, 2}, {2, 3}}
Output: 4 3
Explanation: For Query1 – subarray [2, 4]. 
The ways will be [1, 4] [3, 4] (only 1st position is replaced), and 
[2, 3] [2, 5] (only 2nd position is changed). So number of ways are 4.
For Query2 – subarray [4, 5]. 
The ways are  [1, 5] [2, 5] [3, 5] (only 1st position is replaced). 
Second position cannot be replaced as is already 5 which is equal to K 
and the previous element is 4. There does not exist any element in between. 
So number of ways are 3.

Input: A[] = {1, 3, 4}, K = 4, Q = 1, Queries = {{0, 2}}
Output: 2



Approach: The problem can be solved based on the following idea:

We need to calculate the possible changes for every element in each query so here pre-computed values can save an extra iteration of N for each query separately and each query can be answered in O(1) using the precomputed values in prefix sum.

Follow the following steps to answer each query in constant time.

Below is the implementation of the above approach.




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Array to store precomputed values
int pre[100005];
 
// Function to fill pre array
void precompute(int a[], int N)
{
    for (int i = 0; i < N; i++) {
        if (i == 0) {
 
            // First element can be replaced
            // with every element smaller than
            // next element except itself
            pre[i] = a[1] - 2;
        }
        else {
 
            // If this is not the last element
            if (i != N - 1) {
 
                // Calculate possible values for
                // the current index that it can
                // be replaced with
                pre[i] = a[i + 1] - a[i - 1] - 2;
            }
        }
    }
    for (int i = 1; i < N; i++) {
 
        // Calculating prefix sum
        pre[i] += pre[i - 1];
    }
}
 
// Function to answer the queries
void solve(int Q, int Queries[2][2], int K, int a[], int N)
{
 
    // Precomputing values only if there is
    // more than one element
    if (N > 1) {
 
        // Function call
        precompute(a, N);
    }
 
    // Loop for answering queries
    for (int i = 0; i < Q; i++) {
 
        // Taking L and R from Queries
        int L = Queries[i][0];
        int R = Queries[i][1];
 
        if (L == R) {
 
            // if single element subarray then
            // it can be replaced with K - 1
            // elements
            cout << K - 1 << " ";
        }
        else {
 
            int ans = 0;
 
            // Possible replacements for
            // element at index L
            int left = a[L + 1] - 1;
            ans += (left - 1);
 
            // Possible replacements for
            // element at index R
            int right = a[R - 1] + 1;
            ans += (K - right);
 
            // Possible replacements for
            // element in range [L + 1, R - 1]
            ans += (pre[R - 1] - pre[L]);
 
            // Printing the answer
            cout << ans << " ";
        }
    }
}
 
// Driver Code
int main()
{
    int A[] = { 1, 2, 4, 5 };
    int N = sizeof(A) / sizeof(A[0]);
    int Q = 2, K = 5;
    int Queries[Q][2] = { { 1, 2 }, { 2, 3 } };
 
    // Function call
    solve(Q, Queries, K, A, N);
    return 0;
}




// Java code to implement the approach
import java.io.*;
 
class GFG {
    // Array to store precomputed values
    static int pre[] = new int[100005];
 
    // Function to fill pre array
    public static void precompute(int a[], int N)
    {
        for (int i = 0; i < N; i++) {
            if (i == 0) {
 
                // First element can be replaced
                // with every element smaller than
                // next element except itself
                pre[i] = a[1] - 2;
            }
            else {
 
                // If this is not the last element
                if (i != N - 1) {
 
                    // Calculate possible values for
                    // the current index that it can
                    // be replaced with
                    pre[i] = a[i + 1] - a[i - 1] - 2;
                }
            }
        }
        for (int i = 1; i < N; i++) {
 
            // Calculating prefix sum
            pre[i] += pre[i - 1];
        }
    }
 
    // Function to answer the queries
    public static void solve(int Q, int Queries[][], int K,
                             int a[], int N)
    {
 
        // Precomputing values only if there is
        // more than one element
        if (N > 1) {
 
            // Function call
            precompute(a, N);
        }
 
        // Loop for answering queries
        for (int i = 0; i < Q; i++) {
 
            // Taking L and R from Queries
            int L = Queries[i][0];
            int R = Queries[i][1];
 
            if (L == R) {
 
                // if single element subarray then
                // it can be replaced with K - 1
                // elements
                System.out.print(K - 1 + " ");
            }
            else {
 
                int ans = 0;
 
                // Possible replacements for
                // element at index L
                int left = a[L + 1] - 1;
                ans += (left - 1);
 
                // Possible replacements for
                // element at index R
                int right = a[R - 1] + 1;
                ans += (K - right);
 
                // Possible replacements for
                // element in range [L + 1, R - 1]
                ans += (pre[R - 1] - pre[L]);
 
                // Printing the answer
                System.out.print(ans + " ");
            }
        }
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int A[] = { 1, 2, 4, 5 };
        int N = A.length;
        int Q = 2, K = 5;
        int Queries[][] = { { 1, 2 }, { 2, 3 } };
 
        // Function call
        solve(Q, Queries, K, A, N);
    }
}
 
// This code is contributed by Rohit Pradhan




# Python code to implement the approach
 
# list to store precomputed values
pre = [0]*100005
 
# Function to fill pre array
def precompute(a, N):
  for i in range(N):
    if (i == 0):
       
      # First element can be replaced
      # with every element smaller than
      # next element except itself
      pre[i] = a[1] - 2
    else:
      # If this is not the last element
      if (i != N - 1):
         
        # Calculate possible values for
        # the current index that it can
        # be replaced with
        pre[i] = a[i + 1] - a[i - 1] - 2
  for i in range(1, N):
     
      # Calculating prefix sum
      pre[i] += pre[i - 1]
       
# Function to answer the queries
def solve(Q, Queries, K, a, N):
   
  # Precomputing values only if there is
  # more than one element
  if (N > 1):
     
    # Function call
    precompute(a, N)
     
  # Loop for answering queries
  for i in range(Q):
     
    # Taking L and R from Queries
    L = Queries[i][0]
    R = Queries[i][1]
    if (L == R):
       
      # if single element subarray then
      # it can be replaced with K - 1
      # elements
      print(K - 1, end = " ")
    else:
      ans = 0
       
      # Possible replacements for
      # element at index L
      left = a[L + 1] - 1
      ans += (left - 1)
       
      # Possible replacements for
      # element at index R
      right = a[R - 1] + 1
      ans += (K - right)
       
      # Possible replacements for
      # element in range [L + 1, R - 1]
      ans += (pre[R - 1] - pre[L])
       
      # Printing the answer
      print(ans , end = " ")
       
# Driver Code
A = [1, 2, 4, 5]
N = len(A)
Q = 2
K = 5
Queries = [[1, 2 ], [2, 3]]
 
# Function call
solve(Q, Queries, K, A, N)
 
# This code is contributed by Atul_kumar_shrivastava.




// C# code for the above approach
using System;
using System.Collections.Generic;
 
class GFG {
 
    // Array to store precomputed values
    static int[] pre = new int[100005];
 
    // Function to fill pre array
    public static void precompute(int[] a, int N)
    {
        for (int i = 0; i < N; i++) {
            if (i == 0) {
 
                // First element can be replaced
                // with every element smaller than
                // next element except itself
                pre[i] = a[1] - 2;
            }
            else {
 
                // If this is not the last element
                if (i != N - 1) {
 
                    // Calculate possible values for
                    // the current index that it can
                    // be replaced with
                    pre[i] = a[i + 1] - a[i - 1] - 2;
                }
            }
        }
        for (int i = 1; i < N; i++) {
 
            // Calculating prefix sum
            pre[i] += pre[i - 1];
        }
    }
 
    // Function to answer the queries
    public static void solve(int Q, int[,] Queries, int K,
                             int[] a, int N)
    {
 
        // Precomputing values only if there is
        // more than one element
        if (N > 1) {
 
            // Function call
            precompute(a, N);
        }
 
        // Loop for answering queries
        for (int i = 0; i < Q; i++) {
 
            // Taking L and R from Queries
            int L = Queries[i, 0];
            int R = Queries[i, 1];
 
            if (L == R) {
 
                // if single element subarray then
                // it can be replaced with K - 1
                // elements
                Console.Write(K - 1 + " ");
            }
            else {
 
                int ans = 0;
 
                // Possible replacements for
                // element at index L
                int left = a[L + 1] - 1;
                ans += (left - 1);
 
                // Possible replacements for
                // element at index R
                int right = a[R - 1] + 1;
                ans += (K - right);
 
                // Possible replacements for
                // element in range [L + 1, R - 1]
                ans += (pre[R - 1] - pre[L]);
 
                // Printing the answer
                Console.Write(ans + " ");
            }
        }
    }
 
 
// Driver Code
public static void Main()
{
        int[] A = { 1, 2, 4, 5 };
        int N = A.Length;
        int Q = 2, K = 5;
        int[,] Queries = { { 1, 2 }, { 2, 3 } };
 
        // Function call
        solve(Q, Queries, K, A, N);
}
}
 
// This code is contributed by sanjoy_62.




<script>
// Array to store precomputed values
let pre = [];
for(let i=0;i<100005;i++)
{
    pre[i] = 0;
}
 
// Function to fill pre array
function precompute(a,N)
{
    for (let i = 0; i < N; i++) {
        if (i == 0) {
 
            // First element can be replaced
            // with every element smaller than
            // next element except itself
            pre[i] = a[1] - 2;
        }
        else {
 
            // If this is not the last element
            if (i != N - 1) {
 
                // Calculate possible values for
                // the current index that it can
                // be replaced with
                pre[i] = a[i + 1] - a[i - 1] - 2;
            }
        }
    }
    for (let i = 1; i < N; i++) {
 
        // Calculating prefix sum
        pre[i] += pre[i - 1];
    }
}
 
// Function to answer the queries
function solve( Q,Queries, K, a,N)
{
    // output to be printed
    let output = "";
    // Precomputing values only if there is
    // more than one element
    if (N > 1) {
 
        // Function call
        precompute(a, N);
    }
 
    // Loop for answering queries
    for (let i = 0; i < Q; i++) {
 
        // Taking L and R from Queries
        let L = Queries[i][0];
        let R = Queries[i][1];
 
        if (L == R) {
 
            // if single element subarray then
            // it can be replaced with K - 1
            // elements
             
            let z = K-1;
            output+=z+" ";
        }
        else {
 
            let ans = 0;
 
            // Possible replacements for
            // element at index L
            let left = a[L + 1] - 1;
            ans += (left - 1);
 
            // Possible replacements for
            // element at index R
            let right = a[R - 1] + 1;
            ans += (K - right);
 
            // Possible replacements for
            // element in range [L + 1, R - 1]
            ans += (pre[R - 1] - pre[L]);
 
            // Printing the answer
            output+=ans+" ";
        }
    }
    console.log(output);
}
 
// Driver code
let A = [ 1, 2, 4, 5 ];
let N = A.length;
let Q = 2, K = 5;
let Queries = [ [ 1, 2 ], [ 2, 3 ] ];
 
// Function call
solve(Q, Queries, K, A, N);
 
// This code is contributed by akashish__
</script>

Output
4 3 

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


Article Tags :