但是可以证明最终用到的d的取值最多不超过500
截取一段explanation:
Below is the explanation from yosupo, translated by me.
[From here]
Let m be the number of the islands (that is, 30001). First, let us describe a solution with time and memory complexity of O(m2).
We will apply Dynamic Programming. let dp[i][j] be the number of the gems that Mr. Kitayuta can collect after he jumps to island i, when the length of his previous jump is j (let us assume that he have not collect the gems on island i). Then, you can calculate the values of the table dp by the following:
- dp[i][j] = 0, if i ≥ m
(actually these islands do not exist, but we can suppose that they exist and when Mr. Kitayuta jumps to these islands, he stops jumping) - dp[i][j] = (the number of the gems on island i) + max(dp[i + j][j], dp[i + j + 1][j + 1]), if i < m, j = 1
(he cannot perform a jump of length 0) - dp[i][j] = (the number of the gems on island i) + max(dp[i + j - 1][j - 1], dp[i + j][j], dp[i + j + 1][j + 1]), if i < m, j ≥ 2
This solution is unfeasible in terms of both time and memory. However, the following observation makes it an Accepted solution: there are only 491 values of j that we have to consider, which are d - 245, d - 244, d - 243, ..., d + 244 and d + 245.
Why? First, let us find the upper bound of j. Suppose Mr. Kitayuta always performs the "l + 1" jump (l: the length of the previous jump). Then, he will reach the end of the islands before he performs a jump of length d + 246, because
d + (d + 1) + (d + 2) + ... + (d + 245) ≥ 1 + 2 + ... + 245 = 245·(245 + 1) / 2 = 30135 > 30000. Thus, he will never be able to perform a jump of length d + 246 or longer.
Next, let us consider the lower bound of j in a similar way. If d ≤ 246, then obviously he will not be able to perform a jump of length d - 246 or shorter, because the length of a jump must be positive. Suppose Mr. Kitayuta always performs the "l - 1" jump, where d ≥ 247. Then, again he will reach the end of the islands before he performs a jump of length d - 246, because
d + (d - 1) + (d - 2) + ... + (d - 245) ≥ 245 + 244 + ... + 1 = 245·(245 + 1) / 2 = 30135 > 30000. Thus, he will never be able to perform a jump of length d - 246 or shorter.
Therefore, we have obtained a working solution: similar to the O(m2) one, but we will only consider the value of j between d - 245 andd + 245. The time and memory complexity of this solution will be O(m1.5), since the value "245" is slightly larger than .
This solution can be implemented by, for example, using a "normal" two dimensional array with a offset like this: dp[i][j - offset]
. The time limit is set tight in order to fail most of naive solutions with search using std::map or something, so using hash maps (unordered_map) will be risky although the complexity will be the same as the described solution.
[End]
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
#include<map>
#include<vector>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (30000+10)
#define MAXD (30000+10)
#define M (30001)
#define MP(a,b) make_pair(a,b)
#define MAX_d_change (250+10)
#define C (250)
long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
typedef long long ll;
int n,d,a[MAXN]={0},s[MAXN]={0},f[MAXN][MAX_d_change*2]={0};
int main()
{
// freopen("Treasure.in","r",stdin);
// freopen(".out","w",stdout);
cin>>n>>d;
For(i,n)
{
int p;
scanf("%d",&p);
a[p]++;
}
For(i,M) s[i]=s[i-1]+a[i];
int ans=0;
memset(f,-1,sizeof(f));
ans=f[d][C]=a[d];
Fork(i,d,M)
{
Rep(j,2*C+1)
if (f[i][j]>=0)
{
int dis=j-C+d;
if (dis>0&&i+dis<=M) {f[i+dis][j]=max(f[i+dis][j],f[i][j]+a[i+dis]);ans=max(ans,f[i+dis][j]);}
if (i+dis+1<=M) {f[i+dis+1][j+1]=max(f[i+dis+1][j+1],f[i][j]+a[i+dis+1]);ans=max(ans,f[i+dis+1][j+1]);}
if (dis-1>0&&i+dis-1<=M) {f[i+dis-1][j-1]=max(f[i+dis-1][j-1],f[i][j]+a[i+dis-1]);ans=max(ans,f[i+dis-1][j-1]);}
}
}
cout<<ans<<endl;
return 0;
}