F - Consecutive Subsequence(DP,最长连续递增子序列)

 

链接

 

题目大意

给你n个数的序列,求出最长的连续上升子序列(每个元素之间只差1),并输出在原序列中的位置。

 

 

input
Copy
7
3 3 4 7 5 6 8
output
Copy
4
2 3 5 6
input
Copy
6
1 3 5 2 4 6
output
Copy
2
1 4
input
Copy
4
10 9 8 7
output
Copy
1
1
input
Copy
9
6 7 8 3 4 5 9 10 11
output
Copy
6
1 2 3 7 8 9

 

 思路:  由于子序列的连续递增的性质(x,x+1,x+2……),我们如果考虑令q[i]表示以数字i作为子序列的最后一个元素(即,以数字 i 结尾)的子序列的长度,那么最后一个元素的前一个元素一定是i-1,长度就在前一个的基础上加一。  表示为q[i]=q[i-1]+1。由于给定的n个数字都可以作为子序列的结尾,我们枚举这n个数字,如果有比a[i]小1的数字在a[i]之前出现过,那么q[a[i]-1]一定被更新过,加1后长度增加。如果没有出现过,加1更新为1.

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<utility>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int maxn=2e5+10;
int gcd(int a,int b)
{
    if(!b)
        return a;
    else
        return gcd(b,a%b);
}
int s[maxn];
int a[maxn];
map<int,int>q;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin >> n;
    for(int i=1;i<=n;i++)
    {
        cin >> a[i];
    }
    int maxnum=0;
    int res;
    for(int i=1;i<=n;i++)
    {
        q[a[i]]=q[a[i]-1]+1;
        if(q[a[i]]>maxnum)
        {
            maxnum=q[a[i]];
            res=a[i];
        }
    }

    cout << maxnum  << endl;
    int cnt=0;
    for(int i=n;i>=1;i--)
    {
        if(a[i]==res)
        {
            s[++cnt]=i;
            res--;
        }
    }

    for(int i=cnt;i>=1;i--)
        cout << s[i] << " ";
    return 0;
}

 

posted @ 2020-02-04 23:30  晴天要下雨  阅读(...)  评论(...编辑  收藏