Count ways to make given Subarray strictly increasing by replacing one element for Q queries
Last Updated :
15 Sep, 2022
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.
- Precompute that if ith element is replaced then how many possibilities are there and store it in an array (say pre [ ]).
- A[i] can be replaced by all the elements in the range (A[i-1], A[i+1]) except for A[i] itself. So number of ways = A[i+1] – A[i-1] – 2.
- Calculate the prefix sum in pre[] to store the number of possible ways where pre[i] denotes possible ways from 0 to i.
- Now using prefix sum array we can answer each query by using pre [R] – pre[L – 1].
- But can replace the element at L index with elements from 1 to a[L + 1] – 1 and element at R index from a[R] + 1 to K as the subarray L to R should be sorted by replacing exactly one element.
- So add A[L + 1] – 2 for the position L.
- Similarly, for the last element, add (K – (A[R – 1] + 1)) as the element at position R can begin from A[R – 1] + 1 and go till K.
- Then add all of these different parts and return the final answer.
Below is the implementation of the above approach.
C++14
#include <bits/stdc++.h>
using namespace std;
int pre[100005];
void precompute( int a[], int N)
{
for ( int i = 0; i < N; i++) {
if (i == 0) {
pre[i] = a[1] - 2;
}
else {
if (i != N - 1) {
pre[i] = a[i + 1] - a[i - 1] - 2;
}
}
}
for ( int i = 1; i < N; i++) {
pre[i] += pre[i - 1];
}
}
void solve( int Q, int Queries[2][2], int K, int a[], int N)
{
if (N > 1) {
precompute(a, N);
}
for ( int i = 0; i < Q; i++) {
int L = Queries[i][0];
int R = Queries[i][1];
if (L == R) {
cout << K - 1 << " " ;
}
else {
int ans = 0;
int left = a[L + 1] - 1;
ans += (left - 1);
int right = a[R - 1] + 1;
ans += (K - right);
ans += (pre[R - 1] - pre[L]);
cout << ans << " " ;
}
}
}
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 } };
solve(Q, Queries, K, A, N);
return 0;
}
|
Java
import java.io.*;
class GFG {
static int pre[] = new int [ 100005 ];
public static void precompute( int a[], int N)
{
for ( int i = 0 ; i < N; i++) {
if (i == 0 ) {
pre[i] = a[ 1 ] - 2 ;
}
else {
if (i != N - 1 ) {
pre[i] = a[i + 1 ] - a[i - 1 ] - 2 ;
}
}
}
for ( int i = 1 ; i < N; i++) {
pre[i] += pre[i - 1 ];
}
}
public static void solve( int Q, int Queries[][], int K,
int a[], int N)
{
if (N > 1 ) {
precompute(a, N);
}
for ( int i = 0 ; i < Q; i++) {
int L = Queries[i][ 0 ];
int R = Queries[i][ 1 ];
if (L == R) {
System.out.print(K - 1 + " " );
}
else {
int ans = 0 ;
int left = a[L + 1 ] - 1 ;
ans += (left - 1 );
int right = a[R - 1 ] + 1 ;
ans += (K - right);
ans += (pre[R - 1 ] - pre[L]);
System.out.print(ans + " " );
}
}
}
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 } };
solve(Q, Queries, K, A, N);
}
}
|
Python3
pre = [ 0 ] * 100005
def precompute(a, N):
for i in range (N):
if (i = = 0 ):
pre[i] = a[ 1 ] - 2
else :
if (i ! = N - 1 ):
pre[i] = a[i + 1 ] - a[i - 1 ] - 2
for i in range ( 1 , N):
pre[i] + = pre[i - 1 ]
def solve(Q, Queries, K, a, N):
if (N > 1 ):
precompute(a, N)
for i in range (Q):
L = Queries[i][ 0 ]
R = Queries[i][ 1 ]
if (L = = R):
print (K - 1 , end = " " )
else :
ans = 0
left = a[L + 1 ] - 1
ans + = (left - 1 )
right = a[R - 1 ] + 1
ans + = (K - right)
ans + = (pre[R - 1 ] - pre[L])
print (ans , end = " " )
A = [ 1 , 2 , 4 , 5 ]
N = len (A)
Q = 2
K = 5
Queries = [[ 1 , 2 ], [ 2 , 3 ]]
solve(Q, Queries, K, A, N)
|
C#
using System;
using System.Collections.Generic;
class GFG {
static int [] pre = new int [100005];
public static void precompute( int [] a, int N)
{
for ( int i = 0; i < N; i++) {
if (i == 0) {
pre[i] = a[1] - 2;
}
else {
if (i != N - 1) {
pre[i] = a[i + 1] - a[i - 1] - 2;
}
}
}
for ( int i = 1; i < N; i++) {
pre[i] += pre[i - 1];
}
}
public static void solve( int Q, int [,] Queries, int K,
int [] a, int N)
{
if (N > 1) {
precompute(a, N);
}
for ( int i = 0; i < Q; i++) {
int L = Queries[i, 0];
int R = Queries[i, 1];
if (L == R) {
Console.Write(K - 1 + " " );
}
else {
int ans = 0;
int left = a[L + 1] - 1;
ans += (left - 1);
int right = a[R - 1] + 1;
ans += (K - right);
ans += (pre[R - 1] - pre[L]);
Console.Write(ans + " " );
}
}
}
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 } };
solve(Q, Queries, K, A, N);
}
}
|
Javascript
<script>
let pre = [];
for (let i=0;i<100005;i++)
{
pre[i] = 0;
}
function precompute(a,N)
{
for (let i = 0; i < N; i++) {
if (i == 0) {
pre[i] = a[1] - 2;
}
else {
if (i != N - 1) {
pre[i] = a[i + 1] - a[i - 1] - 2;
}
}
}
for (let i = 1; i < N; i++) {
pre[i] += pre[i - 1];
}
}
function solve( Q,Queries, K, a,N)
{
let output = "" ;
if (N > 1) {
precompute(a, N);
}
for (let i = 0; i < Q; i++) {
let L = Queries[i][0];
let R = Queries[i][1];
if (L == R) {
let z = K-1;
output+=z+ " " ;
}
else {
let ans = 0;
let left = a[L + 1] - 1;
ans += (left - 1);
let right = a[R - 1] + 1;
ans += (K - right);
ans += (pre[R - 1] - pre[L]);
output+=ans+ " " ;
}
}
console.log(output);
}
let A = [ 1, 2, 4, 5 ];
let N = A.length;
let Q = 2, K = 5;
let Queries = [ [ 1, 2 ], [ 2, 3 ] ];
solve(Q, Queries, K, A, N);
</script>
|
Time Complexity: O(N + Q)
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...