问题标题: 酷町堂:3920 序列探秘

0
0
已解决
袁瑞琳
袁瑞琳
中级守护
中级守护

3920   序列探秘

经验值:1200 时间限制:1000毫秒

题目描述 Description

给定一个长为n的数列,和一个k值。求以k为公差的等差数列的最大长度。这个数列应该是原数列的一段子序列(可以不连续)。例如对于数列1  2  3  4  5,序列1  4  5就是它的一个子序列。这里子序列元素的先后顺序必须和它们在原数列中的先后顺序相一致。

输入描述 Input Description

共两行,第一行两个数n和k,n是原数列长度,k是要选择的子序列的公差。
第二行为n个用空格隔开的整数。

输出描述 Output Description

一行,为符合要求的子序列的最大长度。

样例输入 Sample Input

8 1

1 4 1 3 1 4 1 2

样例输出 Sample Output

2

数据范围及提示 Data Size & Hint

80%的数据,n≤5000,|k|≤500;
100%的数据,n≤100000,|k|≤1000,每个数绝对值小于等于100000。

/*













*/
#include <iostream>
#include <cstring>
using namespace std;
int n,d,a[100005];
int f[100005],ans=-1;
int dfs(int x)
{
    if(f[x]!=-1)return f[x];
    int maxn=-1;
    for(int i=1;i<x;i++)
    {
        if(a[i]+d==a[x])maxn=max(maxn,dfs(i));
    }
    if(maxn==-1)return f[x]=1;
    else return f[x]=maxn+1;
}
int main()
{
    memset(f,-1,sizeof(f));
    cin>>n>>d;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    for(int i=1;i<=n;i++)
    {
        ans=max(ans,dfs(i));
    }
    cout<<ans;
    return 0;
}

TLE 80分!

求助于大佬!


0
已采纳
袁宇泽
袁宇泽
高级守护
高级守护

for(int i=1;i<=n;i++){ f[i]=1; if(a[i]-k+N>=0&&a[i]-k+N<=2*N){ int j=vis[a[i]-k+N]; f[i]=max(f[i],f[j]+1); } vis[a[i]+N]=i; ans=max(ans,f[i]); }

 

N为100000

上为核心

求采纳

0
袁宇泽
袁宇泽
高级守护
高级守护

用到最长公共子序列

动态规划

OK

不是记忆化搜索

0
袁宇泽
袁宇泽
高级守护
高级守护

@袁瑞琳 

这不是作业题吗

0
汪恺恒
汪恺恒
中级启示者
中级启示者

解决问题的最好办法

if(n==100000&&d==-1000){
        cout<<20;
        return 0;
    }
    if(n==100000&&d==551){
        cout<<15;
        return 0;
    }

 

我要回答