Codeforces Round #479 (Div. 3)F. Consecutive Subsequence(简单dp)

题意:给出一串数字,让你求在这一串数字中最长的连续递增子序列,输出结果为长度和这个子序列的下标。
举个例子
6
1 3 5 2 4 6
那么结果就是
2
1 4(或者2 5或者3 6)

思路:和最长上升子序列有点像,不过是弱化版。

递推公式是mp[x]=mp[x-1]+1
mp[x]表示以数字x结尾的最大长度。
mp是容器map

至于存储就是用pre数组来记录。
pre[i]=j,表示第i个数前面那个数的下标是j

然后就是遍历整个map,寻找一个最大值,找到之后只要用vector记录就行了。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
map<int, int >pos;//存储每个数的位置
map<int, int >mp;//表示以i为结尾的最大长度
int n;
vector<int>v;
int pre[maxn];

int  main() {
    scanf("%d", &n);
    memset(pre, -1, sizeof(pre));
    for(int i = 1; i <= n; i++) {
        int x;
        scanf("%d", &x);
        pos[x] = i;//数字x的位置是i
        if(mp[x-1]) {//如果存在数字x-1
            mp[x] = mp[x - 1] + 1;
            pre[pos[x]] = pos[x - 1];//第i个数的前面的数下标
        } else mp[x] = 1;
    }
    map<int, int>::iterator it;
    int MAX = 0;
    int p = 0;
    for(it = mp.begin(); it != mp.end(); it++) {
        if(it->second > MAX) {
            MAX = it->second;
            p = pos[it->first];
        }
    }
    printf("%d\n", MAX);
    while(p != -1) {
        v.push_back(p);
        p = pre[p];
    }
    reverse(v.begin(), v.end());
    for(int i = 0; i < v.size(); i++) {
        if(i != v.size() - 1) printf("%d ", v[i]);
        else printf("%d\n", v[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/80239759