luoguP3147 [USACO16OPEN]262144
这里有一种非常鬼畜的\(dp\)方法.
令\(dp[i][j]\)表示区间的最大值为\(i\),区间的起始点为\(j\)的区间长度.
\[\therefore dp[i][j]=dp[i-1][j]+dp[i-1][j+dp[i-1][j]]
\]
当然前提是\(dp[i-1][j]\)和\(dp[i-1][j+dp[i-1][j]]\)能够取到.
答案是能够取到的\(dp[I][J]\)中\(I\)的最大值.
如何想到的呢?其实这是一个套路.
如果将\(dp[i][j]\)设为区间起始点为\(i\),区间长度为\(j\)的最大值,\(Then:\)
\(I'm\ happy\ to\ inform\ you\ that\ your\ test\ is\ MLE\)(艹).
但是最大值的范围只有\(\log_2262144\ +40=58\).
于是我们可以对调\(dp\)的参数,于是就得到了这个鬼畜的\(dp\).
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define il inline
#define rg register
#define gi read<int>
using namespace std;
const int O = 1 << 18 | 10;
template<class TT>
il TT read() {
TT o = 0,fl = 1; char ch = getchar();
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') fl = -1, ch = getchar();
while (isdigit(ch)) o = o * 10 + ch - '0', ch = getchar();
return fl * o;
}
int n, dp[58][O], ans;
int main() {
n = gi();
for (int i = 1; i <= n; ++i) dp[gi()][i] = 1;
for (int i = 1; i <= 58; ++i)
for (int j = n; j; --j)
if (dp[i - 1][j] && dp[i - 1][j + dp[i - 1][j]]) {
dp[i][j] = dp[i - 1][j] + dp[i - 1][j + dp[i - 1][j]];
ans = max(ans, i);
}
printf("%d\n", ans);
return 0;
}