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;
}

猜你喜欢

转载自www.cnblogs.com/lylyl/p/11719521.html