AcWing 896. The longest ascending subsequence II 【greedy + two points】

hello Hello, everyone, welcome to visit Lin Shen when seen deer blog, algorithms white, recorded bit by bit to learn everyday, dedicated user-friendly solution to a problem, that is met Shangshang, if insufficient, also requested the exhibitions.

1. Title

Given a sequence of length N, find the longest length of the subsequence whose value is strictly monotonically increasing.

Input format The
first line contains the integer N.

The second line contains N integers, representing the complete sequence.

Output format
Output an integer, indicating the maximum length.

Data range
1≤N≤100000,
−109≤Number in the sequence ≤109
Input example:
7
3 1 2 1 8 5 6
Output example:
4

2. Thinking (greedy + dichotomy) O(nlogn)

The simple version of LIS has a time complexity of O(n^2) and will time out, so we use greedy + two points to do this question. Let's
talk about the greedy idea first:
we define an array q[], and let the q array store the minimum value at the end of the ascending subsequence under the same length. Because if we can receive a larger number, then we must be able to receive a smaller number, and after receiving a smaller number, we can leave more space for us to receive other numbers, making the array The length is longer. It can be proved that the q array must be monotonously rising. The length of the last q array is the answer.
Let's talk about two points:
how to update the q array?
We traverse the original a array, and for each a[i], we look for the largest number x less than a[i] in the q[] array. After finding, we update the next number of x to a[i], because x is the largest number less than a[i], then the next number of x must be greater than or equal to a[i]. This also proves that if the last number of x is also less than a[i], then the largest number in the q array that is less than a[i] is not x but the next number of x (array q monotonically rises) , This is the opposite of our dichotomy.

3. Code

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int a[N];
int q[N];
int main()
{
    
    
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    int len=0;
    for(int i=0;i<n;i++)
    {
    
    
        int l=0,r=len;   
        while(l<r)  //二分去更新数组q
        {
    
    
            int mid=l+r+1>>1;
            if(q[mid]<a[i]) l=mid; 
            else r=mid-1;
        } 
        q[r+1]=a[i]; 
        len=max(len,r+1);
    }
    printf("%d\n",len); 
    return 0;
}


Guess you like

Origin blog.csdn.net/weixin_45629285/article/details/108901706