Codeforces 505C Mr. Kitayuta, the Treasure Hunter【记忆化搜索+分块数据处理】好题

来源:互联网 发布:mac加载字幕的播放器 编辑:程序博客网 时间:2024/05/22 13:43

C. Mr. Kitayuta, the Treasure Hunter

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

The Shuseki Islands are an archipelago of 30001 small islands in the Yutampo Sea. The islands are evenly spaced along a line, numbered from0 to30000 from the west to the east. These islands are known to contain many treasures. There aren gems in the Shuseki Islands in total, and thei-th gem is located on islandpi.

Mr. Kitayuta has just arrived at island 0. With his great jumping ability, he will repeatedly perform jumps between islands to the east according to the following process:

· First, he will jump from island0 to islandd.

· After that, he will continue jumping according to the following rule. Letl be the length of the previous jump, that is, if his previous jump was from islandprev to islandcur, letl = cur - prev. He will perform a jump of length l - 1,l orl + 1 to the east. That is, he will jump to island(cur + l - 1),(cur + l) or(cur + l + 1) (if they exist). The length of a jump must be positive, that is, he cannot perform a jump of length0 whenl = 1. If there is no valid destination, he will stop jumping.

Mr. Kitayuta will collect the gems on the islands visited during the process. Find the maximum number of gems that he can collect.

Input

The first line of the input contains two space-separated integersn andd (1 ≤ n, d ≤ 30000), denoting the number of the gems in the Shuseki Islands and the length of the Mr. Kitayuta's first jump, respectively.

The next n lines describe the location of the gems. Thei-th of them (1 ≤ i ≤ n) contains a integerpi (d ≤ p1 ≤ p2 ≤ ... ≤ pn ≤ 30000), denoting the number of the island that contains the i-th gem.

Output

Print the maximum number of gems that Mr. Kitayuta can collect.

Examples

Input

4 10
10
21
27
27

Output

3

Input

8 8
9
19
28
36
45
55
66
78

Output

6

Input

13 7
8
8
9
16
17
17
18
21
23
24
24
26
30

Output

4

Note

In the first sample, the optimal route is 0  →  10 (+1 gem) →  19 →  27 (+2 gems) → ...

In the second sample, the optimal route is 0 →  8 →  15 →  21 →  28 (+1 gem) →  36 (+1 gem) →  45 (+1 gem) →  55 (+1 gem) →  66 (+1 gem) →  78 (+1 gem) → ...

In the third sample, the optimal route is 0  →  7  →  13 →  18 (+1 gem) →  24 (+2 gems) →  30 (+1 gem) → ...

 

题目大意:

一个长为30000个小岛屿的群岛,初始的时候主人公在第0号岛屿,第一步他将跳到第D个岛屿上,之后其每一步都可以跳上一步的长度,或者是上一步的长度-1(不能为0),或者是上一步的长度+1,一共有N个gems,其位子已知,按照这样的规则进行跳跃,问最多可以拿到多少gems.


思路:


1、首先考虑到记忆化搜索。设定数组为dp【i】【j】表示走到第i个位子,上一跳了j步的情况下能够拿取的最多的数量。

然而因为i最大可达30000,j最大也可达30000.那么明显直接这样开数组是一定会MLE掉的,那么考虑这个J值到底取多少为宜:

①根据记忆化搜索的特性,分析出如果d越大,跳跃幅度越大,深搜次数就越少,其记忆化搜索优化的次数就会越少,反之,如果d越小,其记忆化搜索的次数就会越大。

②那么根据上述特性,我们本机测试,将j不断取小测试,经过测试,直接暴力处理(不用记忆化,直接搜索的做法)当前解的操作次数,当d==2000的时候,操作次数是


约为10^7.CF是单组评测,明显10^7的暴力处理是hold住的。

那么我们处理,当d>2000时,进行暴力Dfs即可。


2、那么我们将数组dp【i】【j】的j开到2100即可(dp【30040】【2100】),然后对d<2000的数据进行记忆化搜索:

①dp【now】【l】=max(dp【now+l】【l】,dp【now+l+1】【l+1】,dp【now+l-1】【l-1】(l-1!=0))+vis【now】(now这个位子有多少个gem)

②那么其解:ans=max(dp【i】【j】),两层for枚举(i,j)点对维护最大值即可。


3、分析时间复杂度:

d>2000:最大操作次数上图所示,约为10^7;

d<2000:O(n*d)【n为最大岛屿编号】,最大操作次数约为10^7;

显然是不会超时的。


Ac代码:

#include<stdio.h>#include<iostream>#include<string.h>using namespace std;int vis[300040];int dp[30040][2100];int ans;int cont;int Dfs(int now,int l){    if(now>30000)    {        return 0;    }    if(dp[now][l]==-1)    {        dp[now][l]=max(Dfs(now+l,l),dp[now][l]);        dp[now][l]=max(Dfs(now+l+1,l+1),dp[now][l]);        if(l-1>0)        dp[now][l]=max(Dfs(now+l-1,l-1),dp[now][l]);        if(vis[now]>0)dp[now][l]+=vis[now];        return dp[now][l];    }    else return dp[now][l];}int Dfs2(int now,int sum,int l){    cont++;    ans=max(ans,sum);    if(now>30000)    {        return 0 ;    }    Dfs2(now+l,sum+vis[now],l);    Dfs2(now+l+1,sum+vis[now],l+1);    if(l-1>0)    Dfs2(now+l-1,sum+vis[now],l-1);}int main(){    int n,d;    while(~scanf("%d%d",&n,&d))    {        memset(dp,-1,sizeof(dp));        memset(vis,0,sizeof(vis));        for(int i=0;i<n;i++)        {            int x;            scanf("%d",&x);            vis[x]++;        }        if(d>2000)        {            ans=0;            Dfs2(d,0,d);            printf("%d\n",ans);            //printf("cont:%d\n",cont);            continue;        }        Dfs(d,d);        ans=0;        for(int i=d;i<=30020;i++)        {            for(int j=1;j<=2050;j++)            {                ans=max(ans,dp[i][j]);            }        }        printf("%d\n",ans);    }}



0 0