贪心+二分求最大上升子序列

 题目描述:

求最大上升子序列,利用贪心+二分的思想,关键注释都在代码块中了。

学习来源链接:https://blog.csdn.net/lxt_Lucia/article/details/81206439,感谢大佬的博客

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
int L, dp[100005], s[100005], len, ll, rr, mm;
int main(){
    while(scanf("%d",&L) != EOF){
        for(int i = 1;i <= L;i++){
            scanf("%d",&s[i]);
        }
        len = 1;
        dp[len] = s[1];
        for(int i = 2;i <= L;i++){
            if(s[i] > dp[len]){         //如果大于当前数列中最后一个数,则前面的数列加上当前数列可以组成一个递增序列。
                dp[++len] = s[i];
            }else{                      //否则就将当前这个数替换到前面数列的合适位置中,为下一个递增数的加入提供便利。
                ll = 1;rr = len;
                while(ll <= rr){
                    mm = (ll + rr) / 2;
                    if(dp[mm] < s[i]){
                        ll = mm + 1;
                    }else{
                        rr = mm - 1;
                    }
                }
                dp[ll] = s[i];
            }
        }
        printf("%d\n",len);
    }

    return 0;
}

/*
总结:
1.使用一个dp数组,dp[i]表示长度为i的上升子序列结尾元素的最小值,对于一个上升子序列,显然其结尾元素越小,越有利于在后面接其他的元素,也就越可能变得更长。(贪心算法思维)
2.其中使用len保存当前能遍历到的序列中够组成的最长的子序列。
3.根据以上,我们只需要维护一个dp数组即可,对于原s[i]中的每一个值,如果s[i]大于dp[len],那我们直接将s[i]加入dp中即可;
4.如果s[i]小于dp[len]呢?那么就去dp数组中找到一个个大于s[i]的数dp[tem],并更新这个数dp[tem]为s[i],这样做是为了向后查找时,让其他元素更有利于接在其后面!
5.OK,到这里就理解到了。
*/

猜你喜欢

转载自blog.csdn.net/qq_40596572/article/details/103540796