📌  相关文章
📜  插入最多一个整数后最长的子段的长度为UpDown

📅  最后修改于: 2021-04-29 01:36:00             🧑  作者: Mango

整数序列(a_1, a_2, ..., a_k)如果不等式被称为UpDown a_1 \leq a_2 \geq a_3 \leq a_4 \geq a_5 ...成立。
给你一个序列(s_1, s_2, s_3, ..., s_n) 。您最多可以在序列中插入一个整数。它可以是任何整数。在添加整数(或选择不添加)UpDown之后,找到新序列的最长子段的长度。
子段是序列的连续部分。也就是说, (b_1, b_2, ..., b_k)将采用以下形式(b_i, b_{i+1}, b_{i+2}, ..., b_j)对于一些ij
在2019年的Zonal Computing Olympiad中提出了这个问题。

例子:

方法:让我们从定义两种类型的序列开始:

  1. UpDown Sequence(UD):形式的序列a_{i} \leq a_{i+1} \geq a_{i+2} ...即,先后顺序是先增加后再开始。
  2. DownUp Sequence(DU):形式的序列a_{i} \geq a_{i+1} \leq a_{i+2} ...即,先从先减小顺序开始。

让我们首先找出UD和DU序列的长度,而无需考虑问题的其他部分。为此,让我们定义f(idx, 1)开始于最长的UpDown序列idxf(idx, 2)开始于最长的DownUp序列idx
的递归关系f是 :-

(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*}

在此,N是序列的长度,状态是1或2,分别代表UD和DU序列。在形成递归关系时,我们使用了以下事实:在UD序列中(a_i, a_{i+1}, a_{i+2}, ..., a_{k}) , 那个部分(a_{i+1}, a_{i+2}, ..., a_{k})是DU序列,反之亦然。我们可以使用动态编程来计算f然后将结果存储在数组dp [N] [2]中
现在,请注意,始终可以在UpDown序列的末尾插入一个整数,以将序列的长度增加1,但仍保留UpDown不等式。为什么 ?假设UD序列在处中断a_k因为a_k > a_{k+1}当我们期望它是a_k \leq a_{k+1} 。我们可以插入一个整数x = a_k之间a_ka_{k+1} 。现在, a_k \leq x \geq a_{k+1}很满意。
对于UD序列在处中断的情况,我们可以给出类似的论点a_k因为a_k > a_{k+1}当我们期望它是a_k \leq a_{k+1} 。但是,我们不必实际插入任何内容。我们必须找到可能的最长UD序列的长度。

请注意,UD序列是以下各项的组合:

  1. 如果UD序列I的长度为奇数,则UD序列I + x + UD序列II
  2. 如果UD序列I的长度是偶数,则UD序列I + x + DU序列I

其中,x是插入的元素。

因此,对于每个i,我们计算从i开始的最长UD序列的长度。令长度为y。
如果y为奇数,则在理论上将一个元素插入其中,并计算从i + y开始的最长UD序列的长度。因此,在插入元素后从i开始的最长UD序列为dp [i] [1] +1 + dp [i + y] [1]

如果y为偶数,则在理论上将一个元素插入那里,然后计算从i + y开始的最长DU序列的长度。因此,在插入元素后从i开始的最长UD序列为dp [i] [1] + 1 + dp [i + y] [2]
最终答案是在所有i中最大的这样的值。

C++
// C++ implementation of the approach
#include 
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 
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


输出:
7

时间复杂度: O(n)
空间复杂度: O(n)