zoukankan      html  css  js  c++  java
  • 模板

    原来B序列并不是最长上升子序列,虽然他确实是上升的,但是顺序不一定对(指它不一定是原序列的一个子序列)。

    最长上升子序列

    模板。

    int LIS() {
        int len = 1;
        B[1] = A[1];
        for(int i = 2; i <= n; ++i) {
            if(A[i] > B[len]) {
                B[++len] = A[i];
            } else {
                int pos = lower_bound(B + 1, B + 1 + len, A[i]) - B;
                B[pos] = A[i];
            }
        }
        return len;
    }
    

    最长不下降子序列

    把上面的大于换成大于等于,把大于等于(lower_bound())换成大于(upper_bound())。

    int LIS() {
        int len = 1;
        B[1] = A[1];
        for(int i = 2; i <= n; ++i) {
            if(A[i] >= B[len]) {
                B[++len] = A[i];
            } else {
                int pos = upper_bound(B + 1, B + 1 + len, A[i]) - B;
                B[pos] = A[i];
            }
        }
        return len;
    }
    

    构造

    例题

    CF - 1296E2

    题目链接https://codeforces.com/contest/1296/problem/E2

    这里要求最长下降子序列的长度,并划分为若干个不下降子序列。于是把数字全部取反,转化成求最长上升子序列的长度,并划分为若干个不上升的子序列。

    考虑 (B[x]) 的意思是当前字符串长度为 (x) 的上升子序列的最优结尾字符,在lower_bound()找到 (pos) 之后就说明 (A[i]) 这个字符是可以替换掉 (B[pos]) 原本的字符的,所以在进行链划分的时候可以直接接在这个字符的后面!

    int n;
    char s[200005];
    int A[200005];
    int B[200005];
    int id[200005];
    int C[200005];
    
    int LIS() {
        int len = 1;
        B[1] = A[1];
        C[1] = 1;
        id[1] = 1;
        for(int i = 2; i <= n; ++i) {
            if(A[i] > B[len]) {
                B[++len] = A[i];
                C[i] = len;
                id[len] = i;
            } else {
                int pos = lower_bound(B + 1, B + 1 + len, A[i]) - B;
                B[pos] = A[i];
                C[i] = C[id[pos]];
                id[pos] = i;
            }
        }
        return len;
    }
    
    void test_case() {
        scanf("%d%s", &n, s + 1);
        for(int i = 1; i <= n; ++i)
            A[i] = 'z' + 1 - s[i];
        int len = LIS();
        printf("%d
    ", len);
        for(int i = 1; i <= n; ++i)
            printf("%d%c", C[i], " 
    "[i == n]);
    }
    

    从这里可以得到启发,每次找到一个位置之后都往接在原来的后面,在得到最长上升子序列的同时就会得到一个不下降子序列的链划分。且把这些链的末端连起来应该就是最长上升子序列。

    参考资料

    https://blog.csdn.net/lxt_Lucia/article/details/81206439
    https://www.cnblogs.com/yuelian/p/8745807.html

  • 相关阅读:
    java的语法基础(二)
    MyBatis 的好处是什么?
    python中字符串的编码和解码
    Spring的简介和优点?
    相对于Statement,PreparedStatement的优点是什么?
    MyBatis 的好处是什么?
    .final finally finalize区别
    final类有什么用
    web广泛用到的技术:
    JDK,JRE,JVM三者的关系
  • 原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12294114.html
Copyright © 2011-2022 走看看