Open In App

Length of the longest subsegment which is UpDown after inserting atmost one integer

Improve
Improve
Like Article
Like
Save
Share
Report

A sequence of integers (a_1, a_2, ..., a_k)     is said to be UpDown, if the inequality a_1 \leq a_2 \geq a_3 \leq a_4 \geq a_5 ...     holds true.
You are given a sequence (s_1, s_2, s_3, ..., s_n)     . You can insert at most one integer in the sequence. It could be any integer. Find the length of the longest subsegment of the new sequence after adding an integer (or choosing not to) which is UpDown. 
A subsegment is a consecutive portion of a sequence. That is, a subsegment of (b_1, b_2, ..., b_k)     will be of the form (b_i, b_{i+1}, b_{i+2}, ..., b_j)     for some i     and j
This problem was asked in Zonal Computing Olympiad 2019.
Examples: 
 

Input: arr[] = {1, 10, 3, 20, 25, 24} 
Output:
Suppose we insert 5 between 20 and 25, the whole sequence (1, 10, 3, 20, 5, 25, 24)
becomes an UpDown Sequence and hence the answer is 7.
Input: arr[] = {100, 1, 10, 3, 4, 6, 11} 
Output:
Suppose we insert 4 between 4 and 6, the sequence (1, 10, 3, 4, 4, 6) becomes an UpDown
Sequence and hence the answer is 6. We can verify that this is the best possible
solution. 
 


 


Approach: Let us begin by defining two types of sequence:- 
 

  1. UpDown Sequence (UD) : A sequence of the form a_{i} \leq a_{i+1} \geq a_{i+2} ...     That is, the sequence starts by increasing first.
  2. DownUp Sequence (DU) : A sequence of the form a_{i} \geq a_{i+1} \leq a_{i+2} ...     That is, the sequence starts by decreasing first.


Let us first find out the length of UD and DU sequences without thinking about other parts of the problem. For that, let us define f(idx, 1)     to be the longest UpDown sequence beginning at idx     and f(idx, 2)     to be the longest DownUp sequence beginning at idx     .
Recurrence relation for f     is :- 

(1)   \begin{equation*} f(idx, state)=\begin{cases} 1, idx = N\\ 1, \text{$state = 1 \ and \ s_i > s_{i+1}$}\\ 1, \text{$state = 2 \ and \ s_{i+1} > s_i$}\\ 1 + f(idx+1, 2), \text{$state=1 \ and \ s_i \leq \ s_{i+1}$}\\ 1 + f(idx+1, 1), \text{$state=2 \ and \ s_{i+1} \leq \ s_i$}\\ \end{cases} \end{equation*}


Here, N is the length of the sequence and state is either 1 or 2 and stands for UD and DU sequence respectively. While forming the recurrence relation, we used the fact that In an UD sequence     , the part     is a DU sequence and vice-versa. We can use Dynamic Programming to calculate the value of f     and then store our result in array dp[N][2].
Now, notice that it is always possible to insert an integer at the end of an UpDown sequence to increase the length of the sequence by 1 and yet retain the UpDown inequality. Why ? Suppose an UD sequence breaks at a_k     because a_k > a_{k+1}     when we expected it to be a_k \leq a_{k+1}     . We can insert an integer x = a_k     between a_k     and a_{k+1}     . Now, a_k \leq x \geq a_{k+1}     is satisfied. 
We can give similar argument for the case when UD sequence breaks at a_k     because a_k > a_{k+1}     when we expected it to be a_k \leq a_{k+1}     . But we don’t have to actually insert anything. We have to just find the length of the longest UD sequence possible.
Observe that a UD sequence is a combination of :- 
 

  1. UD sequence I + x + UD sequence II if the length of UD sequence I is odd
  2. UD sequence I + x + DU sequence I if the length of UD sequence I is even


where, x is the inserted element.
So for each i, we calculate the length of the longest UD sequence starting at i. Let that length be y. 
If y is odd, we insert an element there (theoretically) and calculate the length of longest UD sequence starting at i+y. The longest UD sequence beginning at i after inserting an element is therefore dp[i][1] + 1 + dp[i+y][1].
If y is even, we insert an element there (theoretically) and calculate the length of longest DU sequence starting at i+y. The longest UD sequence beginning at i after inserting an element is therefore dp[i][1] + 1 + dp[i+y][2]
The final answer is maximum such value among all i. 
 

C++

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to recursively fill the dp array
int f(int i, int state, int A[], int dp[][3], int N)
{
    if (i >= N)
        return 0;
 
    // If f(i, state) is already calculated
    // then return the value
    else if (dp[i][state] != -1) {
        return dp[i][state];
    }
 
    // Calculate f(i, state) according to the
    // recurrence relation and store in dp[][]
    else {
        if (i == N - 1)
            dp[i][state] = 1;
        else if (state == 1 && A[i] > A[i + 1])
            dp[i][state] = 1;
        else if (state == 2 && A[i] < A[i + 1])
            dp[i][state] = 1;
        else if (state == 1 && A[i] <= A[i + 1])
            dp[i][state] = 1 + f(i + 1, 2, A, dp, N);
        else if (state == 2 && A[i] >= A[i + 1])
            dp[i][state] = 1 + f(i + 1, 1, A, dp, N);
        return dp[i][state];
    }
}
 
// Function that calls the resucrsive function to
// fill the dp array and then returns the result
int maxLenSeq(int A[], int N)
{
    int i, tmp, y, ans;
 
    // dp[][] array for storing result
    // of f(i, 1) and f(1, 2)
    int dp[1000][3];
 
    // Populating the array dp[] with -1
    memset(dp, -1, sizeof dp);
 
    // Make sure that longest UD and DU
    // sequence starting at each
    // index is calculated
    for (i = 0; i < N; i++) {
        tmp = f(i, 1, A, dp, N);
        tmp = f(i, 2, A, dp, N);
    }
 
    // Assume the answer to be -1
    // This value will only increase
    ans = -1;
    for (i = 0; i < N; i++) {
 
        // y is the length of the longest
        // UD sequence starting at i
        y = dp[i][1];
 
        if (i + y >= N)
            ans = max(ans, dp[i][1] + 1);
 
        // If length is even then add an integer
        // and then a DU sequence starting at i + y
        else if (y % 2 == 0) {
            ans = max(ans, dp[i][1] + 1 + dp[i + y][2]);
        }
 
        // If length is odd then add an integer
        // and then a UD sequence starting at i + y
        else if (y % 2 == 1) {
            ans = max(ans, dp[i][1] + 1 + dp[i + y][1]);
        }
    }
    return ans;
}
 
// Driver code
int main()
{
    int A[] = { 1, 10, 3, 20, 25, 24 };
    int n = sizeof(A) / sizeof(int);
 
    cout << maxLenSeq(A, n);
 
    return 0;
}

                    

Java

// Java implementation of the approach
import java.io.*;
public class GFG
{
     
    // Function to recursively fill the dp array
    static int f(int i, int state, int A[],
                 int dp[][], int N)
    {
        if (i >= N)
            return 0;
     
        // If f(i, state) is already calculated
        // then return the value
        else if (dp[i][state] != -1)
        {
            return dp[i][state];
        }
     
        // Calculate f(i, state) according to the
        // recurrence relation and store in dp[][]
        else
        {
            if (i == N - 1)
                dp[i][state] = 1;
            else if (state == 1 && A[i] > A[i + 1])
                dp[i][state] = 1;
            else if (state == 2 && A[i] < A[i + 1])
                dp[i][state] = 1;
            else if (state == 1 && A[i] <= A[i + 1])
                dp[i][state] = 1 + f(i + 1, 2, A, dp, N);
            else if (state == 2 && A[i] >= A[i + 1])
                dp[i][state] = 1 + f(i + 1, 1, A, dp, N);
            return dp[i][state];
        }
    }
     
    // Function that calls the resucrsive function to
    // fill the dp array and then returns the result
    static int maxLenSeq(int A[], int N)
    {
        int i,j, tmp, y, ans;
     
        // dp[][] array for storing result
        // of f(i, 1) and f(1, 2)
        int dp[][] = new int[1000][3];
         
        // Populating the array dp[] with -1
        for(i= 0; i < 1000; i++)
            for(j = 0; j < 3; j++)
                dp[i][j] = -1;
 
        // Make sure that longest UD and DU
        // sequence starting at each
        // index is calculated
        for (i = 0; i < N; i++)
        {
            tmp = f(i, 1, A, dp, N);
            tmp = f(i, 2, A, dp, N);
        }
     
        // Assume the answer to be -1
        // This value will only increase
        ans = -1;
        for (i = 0; i < N; i++)
        {
     
            // y is the length of the longest
            // UD sequence starting at i
            y = dp[i][1];
     
            if (i + y >= N)
                ans = Math.max(ans, dp[i][1] + 1);
     
            // If length is even then add an integer
            // and then a DU sequence starting at i + y
            else if (y % 2 == 0)
            {
                ans = Math.max(ans, dp[i][1] + 1 + dp[i + y][2]);
            }
     
            // If length is odd then add an integer
            // and then a UD sequence starting at i + y
            else if (y % 2 == 1)
            {
                ans = Math.max(ans, dp[i][1] + 1 + dp[i + y][1]);
            }
        }
        return ans;
    }
     
    // Driver code
    public static void main (String[] args)
    {
        int A[] = { 1, 10, 3, 20, 25, 24 };
        int n = A.length;
     
        System.out.println(maxLenSeq(A, n));
    }
}
 
// This code is contributed by AnkitRai01

                    

Python3

# Python3 implementation of the approach
 
# Function to recursively fill the dp array
def f(i, state, A, dp, N):
    if i >= N:
        return 0
 
    # If f(i, state) is already calculated
    # then return the value
    elif dp[i][state] != -1:
        return dp[i][state]
 
    # Calculate f(i, state) according to the
    # recurrence relation and store in dp[][]
    else:
        if i == N - 1:
            dp[i][state] = 1
        elif state == 1 and A[i] > A[i + 1]:
            dp[i][state] = 1
        elif state == 2 and A[i] < A[i + 1]:
            dp[i][state] = 1
        elif state == 1 and A[i] <= A[i + 1]:
            dp[i][state] = 1 + f(i + 1, 2, A, dp, N)
        elif state == 2 and A[i] >= A[i + 1]:
            dp[i][state] = 1 + f(i + 1, 1, A, dp, N)
 
        return dp[i][state]
 
# Function that calls the resucrsive function to
# fill the dp array and then returns the result
def maxLenSeq(A, N):
 
    # dp[][] array for storing result
    # of f(i, 1) and f(1, 2)
    # Populating the array dp[] with -1
    dp = [[-1, -1, -1] for i in range(1000)]
 
    # Make sure that longest UD and DU
    # sequence starting at each
    # index is calculated
    for i in range(N):
        tmp = f(i, 1, A, dp, N)
        tmp = f(i, 2, A, dp, N)
 
    # Assume the answer to be -1
    # This value will only increase
    ans = -1
    for i in range(N):
 
        # y is the length of the longest
        # UD sequence starting at i
        y = dp[i][1]
        if (i + y) >= N:
            ans = max(ans, dp[i][1] + 1)
 
        # If length is even then add an integer
        # and then a DU sequence starting at i + y
        elif y % 2 == 0:
            ans = max(ans, dp[i][1] + 1 + dp[i + y][2])
 
        # If length is odd then add an integer
        # and then a UD sequence starting at i + y
        elif y % 2 == 1:
            ans = max(ans, dp[i][1] + 1 + dp[i + y][1])
 
    return ans
 
# Driver Code
if __name__ == "__main__":
    A = [1, 10, 3, 20, 25, 24]
    n = len(A)
    print(maxLenSeq(A, n))
 
# This code is contributed by
# sanjeev2552

                    

C#

// C# implementation of the approach
using System;
     
class GFG
{
     
    // Function to recursively fill the dp array
    static int f(int i, int state, int []A,
                 int [,]dp, int N)
    {
        if (i >= N)
            return 0;
     
        // If f(i, state) is already calculated
        // then return the value
        else if (dp[i, state] != -1)
        {
            return dp[i, state];
        }
     
        // Calculate f(i, state) according to the
        // recurrence relation and store in dp[,]
        else
        {
            if (i == N - 1)
                dp[i, state] = 1;
            else if (state == 1 && A[i] > A[i + 1])
                dp[i, state] = 1;
            else if (state == 2 && A[i] < A[i + 1])
                dp[i, state] = 1;
            else if (state == 1 && A[i] <= A[i + 1])
                dp[i, state] = 1 + f(i + 1, 2, A, dp, N);
            else if (state == 2 && A[i] >= A[i + 1])
                dp[i, state] = 1 + f(i + 1, 1, A, dp, N);
            return dp[i, state];
        }
    }
     
    // Function that calls the resucrsive function to
    // fill the dp array and then returns the result
    static int maxLenSeq(int []A, int N)
    {
        int i, j, tmp, y, ans;
     
        // dp[,] array for storing result
        // of f(i, 1) and f(1, 2)
        int [,]dp = new int[1000, 3];
         
        // Populating the array dp[] with -1
        for(i = 0; i < 1000; i++)
            for(j = 0; j < 3; j++)
                dp[i, j] = -1;
 
        // Make sure that longest UD and DU
        // sequence starting at each
        // index is calculated
        for (i = 0; i < N; i++)
        {
            tmp = f(i, 1, A, dp, N);
            tmp = f(i, 2, A, dp, N);
        }
     
        // Assume the answer to be -1
        // This value will only increase
        ans = -1;
        for (i = 0; i < N; i++)
        {
     
            // y is the length of the longest
            // UD sequence starting at i
            y = dp[i, 1];
     
            if (i + y >= N)
                ans = Math.Max(ans, dp[i, 1] + 1);
     
            // If length is even then add an integer
            // and then a DU sequence starting at i + y
            else if (y % 2 == 0)
            {
                ans = Math.Max(ans, dp[i, 1] + 1 +
                                    dp[i + y, 2]);
            }
     
            // If length is odd then add an integer
            // and then a UD sequence starting at i + y
            else if (y % 2 == 1)
            {
                ans = Math.Max(ans, dp[i, 1] + 1 +
                                    dp[i + y, 1]);
            }
        }
        return ans;
    }
     
    // Driver code
    public static void Main (String[] args)
    {
        int []A = { 1, 10, 3, 20, 25, 24 };
        int n = A.Length;
     
        Console.WriteLine(maxLenSeq(A, n));
    }
}
 
// This code is contributed by 29AjayKumar

                    

Javascript

<script>
    // Javascript implementation of the approach
     
    // Function to recursively fill the dp array
    function f(i, state, A, dp, N)
    {
        if (i >= N)
            return 0;
      
        // If f(i, state) is already calculated
        // then return the value
        else if (dp[i][state] != -1)
        {
            return dp[i][state];
        }
      
        // Calculate f(i, state) according to the
        // recurrence relation and store in dp[][]
        else
        {
            if (i == N - 1)
                dp[i][state] = 1;
            else if (state == 1 && A[i] > A[i + 1])
                dp[i][state] = 1;
            else if (state == 2 && A[i] < A[i + 1])
                dp[i][state] = 1;
            else if (state == 1 && A[i] <= A[i + 1])
                dp[i][state] = 1 + f(i + 1, 2, A, dp, N);
            else if (state == 2 && A[i] >= A[i + 1])
                dp[i][state] = 1 + f(i + 1, 1, A, dp, N);
            return dp[i][state];
        }
    }
      
    // Function that calls the resucrsive function to
    // fill the dp array and then returns the result
    function maxLenSeq(A, N)
    {
        let i,j, tmp, y, ans;
      
        // dp[][] array for storing result
        // of f(i, 1) and f(1, 2)
        let dp = new Array(1000);
          
        // Populating the array dp[] with -1
        for(i= 0; i < 1000; i++)
        {
            dp[i] = new Array(3);
            for(j = 0; j < 3; j++)
            {
                dp[i][j] = -1;
            }
        }
  
        // Make sure that longest UD and DU
        // sequence starting at each
        // index is calculated
        for (i = 0; i < N; i++)
        {
            tmp = f(i, 1, A, dp, N);
            tmp = f(i, 2, A, dp, N);
        }
      
        // Assume the answer to be -1
        // This value will only increase
        ans = -1;
        for (i = 0; i < N; i++)
        {
      
            // y is the length of the longest
            // UD sequence starting at i
            y = dp[i][1];
      
            if (i + y >= N)
                ans = Math.max(ans, dp[i][1] + 1);
      
            // If length is even then add an integer
            // and then a DU sequence starting at i + y
            else if (y % 2 == 0)
            {
                ans = Math.max(ans, dp[i][1] + 1 + dp[i + y][2]);
            }
      
            // If length is odd then add an integer
            // and then a UD sequence starting at i + y
            else if (y % 2 == 1)
            {
                ans = Math.max(ans, dp[i][1] + 1 + dp[i + y][1]);
            }
        }
        return ans;
    }
     
    let A = [ 1, 10, 3, 20, 25, 24 ];
    let n = A.length;
 
    document.write(maxLenSeq(A, n));
             
</script>

                    

Output
7

Time Complexity: O(n) 
Space Complexity: O(n)
 



Last Updated : 01 Nov, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads