luoguP3147 [USACO16OPEN]262144
Posted lylyl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luoguP3147 [USACO16OPEN]262144相关的知识,希望对你有一定的参考价值。
这里有一种非常鬼畜的(dp)方法.
令(dp[i][j])表示区间的最大值为$ i (,区间的起始点为) j $的区间长度.
[
herefore 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
", ans);
return 0;
}
以上是关于luoguP3147 [USACO16OPEN]262144的主要内容,如果未能解决你的问题,请参考以下文章
luogu P3147 [USACO16OPEN]262144
[luoguP3146] [USACO16OPEN]248(区间DP)