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;
}
posted @ 2019-10-22 14:19  wuhan2005  阅读(85)  评论(0编辑  收藏  举报