• codeforces 486 E. LIS of Sequence(dp)


    题目链接:http://codeforces.com/contest/486/problem/E

    题意:给出n个数,如果一个数满足不属于最长递增序列,那么输出1,如果属于最长递增序列但是不属于所有最长递增序列的输出2。

    如果属于所有最长递增序列的输出3。

    题解:这里要用点技巧,不妨设dpBefore[i]表示以第i位为结尾的最长递增序列长,dpAfter[i]表示以第i位为结尾的最长递增序列长。

    然后只要满足dpBefore[i]+dpAfter[i]=len(len表示最长递增序列为多长用二分的lis求的),至于这个点是属于所有的递增序列还

    是不是,只要存在j使得dpAfter[i]=dpAfter[j],那么就是不属于所有的最长递增序列。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    const int M = 1e5 + 10;
    int a[M] , b[M] , a2[M] , b2[M] , dpBefore[M] , dpAfter[M] , flag[M] , cmp[M];
    int binsearch(int num , int sta , int end) {
        int l = sta , r = end;
        int mid = (l + r) >> 1;
        while(l <= r) {
            mid = (l + r) >> 1;
            if(b[mid] < num) l = mid + 1;
            else r = mid - 1;
        }
        return r;
    }
    int binsearch2(int num , int sta , int end) {
        int l = sta , r = end;
        int mid = (l + r) >> 1;
        while(l <= r) {
            mid = (l + r) >> 1;
            if(b2[mid] <= num) l = mid + 1;
            else r = mid - 1;
        }
        return l;
    }
    int main() {
        int n;
        scanf("%d" , &n);
        memset(cmp , 0 , sizeof(cmp));
        for(int i = 1 ; i <= n ; i++) {
            scanf("%d" , &a[i]);
            a2[i] = a[i];
            flag[i] = 0;
        }
        int len = 1;
        b[len] = a[1];
        for(int i = 2 ; i <= n ; i++) {
            if(a[i] > b[len]) {
                b[++len] = a[i];
                dpBefore[i] = len - 1;
            }
            else {
                int pos = binsearch(a[i] , 1 , len);
                b[pos + 1] = a[i];
                dpBefore[i] = pos;
            }
        }
        int len2 = len;
        b2[len2] = a[n];
        for(int i = n - 1 ; i >= 1 ; i--) {
            if(a[i] < b2[len2]) {
                b2[--len2] = a[i];
                dpAfter[i] = len - len2;
            }
            else {
                int pos = binsearch2(a[i] , len2 , len);
                b2[pos - 1] = a[i];
                dpAfter[i] = len - pos + 1;
            }
        }
    
        for(int i = 1 ; i <= n ; i++) {
            if(dpBefore[i] + dpAfter[i] == len - 1) {
                flag[i] = 1;
                cmp[dpAfter[i]]++;
            }
        }
        for(int i = 1 ; i <= n ; i++) {
            if(flag[i]) {
                if(cmp[dpAfter[i]] > 1) {
                    printf("2");
                }
                else {
                    printf("3");
                }
            }
            else {
                printf("1");
            }
        }
        printf("
    ");
        return 0;
    }
    
  • 相关阅读:
    程序员新年要实现的10个愿望
    编写超级可读代码的15个最佳实践
    LeetCode 最大子序和
    LeetCode 最大正方形
    LeetCode 买卖股票的最佳时机 II
    LeetCode 买卖股票的最佳时机
    B树和B+树
    SQL的几种连接
    LeetCode 无重复字符的最长子串
    LeetCode 翻转字符串里的单词
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6714512.html
Copyright © 2020-2023  润新知