计蒜客-The Heaviest Non-decreasing Subsequence Problem(动态规划)

这道题看起来不难,本来没看数据大小,写了一个n^2的最长上升子序列常规解法,结果超时了。回来一看这数据量确实有点大。

然后发现这道题用到的是最长上升子序列的nlogn解法,不太了解的同学可以参见我这篇博客。https://blog.csdn.net/a1097304791/article/details/82286906

然后把小于0的数去掉,大于等于10000连写5遍就可以直接套板子了

//最重非递减子序列
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int MAXN = 1e6+5;
int a[MAXN], b[MAXN];

//用二分查找的方法找到一个位置,使得num>b[i-1] 并且num<b[i],并用num代替b[i]
int Search(int num, int low, int high) {
    int mid;
    while(low <= high) {
        mid = (low + high) / 2;
        if(num >= b[mid])
            low = mid + 1;
        else
            high = mid - 1;
    }
    return low;
}

int DP(int n) {
    int i, len, pos;
    b[1] = a[1];
    len = 1;
    for(i = 2; i <= n; i++) {
        if(a[i] >= b[len]) { //如果a[i]比b[]数组中最大还大直接插入到后面即可
            len = len + 1;
            b[len] = a[i];
        } else { //用二分的方法在b[]数组中找出第一个比a[i]大的位置并且让a[i]替代这个位置
            pos = Search(a[i], 1, len);
            b[pos] = a[i];
        }
    }
    return len;
}


int main() {
    int input, index = 1;
    memset(a, 0, sizeof(a));
    while(scanf("%d", &input) != EOF) {
        a[index] = input;
        if(input < 0) //把负数直接去掉
            index--;
        else if(input >= 10000) { //把后5个数全变为input-10000
            for(int i = index; i <= index+4; i++)
                a[i] = input - 10000;
            index+=4;
        }
        index++;
    }
    printf("%d\n",DP(index-1));
    return 0;
}

也附上模板,实在不了解的同学记一下模板下次直接用就行。

const int MAXN = 500010;
int a[MAXN], b[MAXN];

//用二分查找的方法找到一个位置,使得num>b[i-1] 并且num<b[i],并用num代替b[i]
int Search(int num, int low, int high) {
    int mid;
    while(low <= high) {
        mid = (low + high) / 2;
        if(num >= b[mid])
            low = mid + 1;
        else
            high = mid - 1;
    }
    return low;
}
int DP(int n) {
    int i, len, pos;
    b[1] = a[1];
    len = 1;
    for(i = 2; i <= n; i++) {
        if(a[i] >= b[len]) { //如果a[i]比b[]数组中最大还大直接插入到后面即可
            len = len + 1;
            b[len] = a[i];
        } else { //用二分的方法在b[]数组中找出第一个比a[i]大的位置并且让a[i]替代这个位置
            pos = Search(a[i], 1, len);
            b[pos] = a[i];
        }
    }
    return len;
}

猜你喜欢

转载自blog.csdn.net/a1097304791/article/details/82287362