• 洛谷 P3902 递增


     1 #include<cstdio>
     2 #include<stdlib.h>
     3 #include<algorithm>
     4 #define INF 10000000000
     5 #define LL long long
     6 using namespace std;
     7 
     8 int a[100001] = { 0 };
     9 LL dp[100001];
    10 
    11 int main(void) {
    12     int n;
    13 
    14     scanf("%d", &n);
    15     for (int i = 0; i < n; i++)
    16         scanf("%d", &a[i]);
    17 
    18     fill(dp, dp + n, INF);
    19     /*与memset()函数的区别:
    20     两者都可以用来对数组填充,memset是对按照字节来填充的,
    21     所以一般用来填充char型数组,也经常用于填充int型的全0或全 - 1操作
    22     fill是按照单元来填充的,所以可以填充一个区间的任意值。*/
    23     for (int i = 0; i < n; i++)
    24         *lower_bound(dp, dp + n, a[i]) = a[i];
    25     //上面这步,主要是不断插入a[i]到dp中:在满足找到大于等于dp[]的第一个位置时
    26     //因为dp中存的是最长上升子序列的子元素
    27     //lower_bound()函数求出来的 dp[n-1]是最长上升序列,所以要减一下。。
    28     printf("%d
    ", n - (lower_bound(dp, dp + n, INF) - dp));
    29     return 0;
    30 }

     这个插入的方式我举一个例子,比如4 2 3 1 5

    因为所有的元素都是一个很大的值,而lower_bound()函数是找到大于等于参数的第一个位置

    那么第一次插入地点在下标为0的地方

      i 0 1 2 3 4
    dp[i] 4

     之后,插入2的时候,因为dp[0] 就已经大于2了,所以用2替换掉4

      i 0 1 2 3 4
    dp[i] 2

    插入3,可知在下标为1时,插入

     i 0 1 2 3 4
    dp[i] 2 3

    之后插入1,发现在第一个位置,即可替换,

     i 0 1 2 3 4
    dp[i] 1 3

    最后插入5

     i 0 1 2 3 4
    dp[i] 1 3 5

    有点费劲,我举个例子

    你比如 4是第一个元素,那之后如果碰到比4还要大的数,是不是直接添加到4之后就可以。那如果4 和这个比4大的数 之间有比4小的,那直接相当于添加在4后面,把原本的数覆盖。

    比如 4 5 之后如果是2,那么在dp中 4 5 就相当于 2 5 ,其实也就是这个意思:

    比如dp中的4 可以被2取代,因为如果碰到 比2大的可以直接加在2后面覆盖掉5,比如4 5 2 3,那就是2 3

    ,碰到比4大的,也就直接加 那第一个存的就是2了,比如4 5 2 6,那就是2 5 6。 主要是长度就是最长上升序列,跟里面的元素关系不是很大,里面的元素是最长序列元素

    就可以不断放进去,这样既保留了原来的dp最大长度,又可以内部更新

    额,,大致是这么个意思,就是不断更新dp,自己也理解的不是很清楚,只是有点想法先记录下。

  • 相关阅读:
    fastjson-alibaba
    ubuntu 入门
    资料文档
    asp.net mvc View视图相关
    视频
    js第三方
    工具类网址
    [转]初学者的编程自学指南
    seajs的使用--主要了解模块化
    其它
  • 原文地址:https://www.cnblogs.com/letianpaiai/p/12838924.html
Copyright © 2020-2023  润新知