codeforces 977f Consecutive Subsequence(dp)

这里写图片描述

题意就是让你找一个最长的公差为1的等差数列,然后输出他们的下标。
分析:
直接用LIS来做会超时,O(N*N),数量级10e+5。
我们可以借助map,因为我们需要顺序的从这个序列里找,可以每次把进来的数标记由前面一个数 + 1得到,即可以得到到这个数为止的最长序列的长度。

比如 3 3 4 7 5 6 8

3 的时候 我们就以m【2】 + 1 得到这个m【3】,但是因为m【2】没出现过,所以直接就是1,然后下一个3也是如此,4的时候就由m【3】 + 1 ,所以m【4】 = 2,然后依次到8,就可以在m【8】的位置保存到从0到8中,最长的序列长度。
边赋值,边找到最大值的下标和数,然后找到以后,有个最大值,用最大值减去长度 + 1是不是就可以得到他的起始数字了,然后再遍历一遍序列,找每个数就可以了,输出下标。

#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
#define inf 0x3f3f3f3f
#define For(a,b) for(int a=0;a<b;a++)
#define mem(x) memset(x,0,sizeof(x))
#define Debug(x) cout<<"---> "<<x<<endl;
#define sf scanf
#define pf printf
int gcd(int a,int b){ return b>0?gcd(b,a%b):a;}
typedef long long ll;
typedef pair<int ,int > P;
//head
#define maxn 300010
int n,a[maxn],ans=0,Max,tag;
map<int,int> mp;
vector<int> ve;

int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        mp[a[i]]=max(mp[a[i]],mp[a[i]-1]+1);
        if(mp[a[i]]>Max){
            Max=mp[a[i]];
            tag=a[i];
        }
    }
    cout<<Max<<endl;

    for(int i=n;i>=1;i--){
        if(a[i]==tag){
            ve.push_back(i);
            tag--;
        }
    }

/*    vector<int>::iterator ite;
    for(ite=ve.end();ite!=ve.begin();--ite){
        cout<<*ite<<" ";
    }
 */
    int sz=ve.size();
    for(int i=sz-1;i>=0;i--){
        cout<<ve[i]<<" ";
    }
    cout<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37360631/article/details/81357051