其他分享
首页 > 其他分享> > P3147 [USACO16OPEN]262144 P(dp)

P3147 [USACO16OPEN]262144 P(dp)

作者:互联网

目录

Description

每两个相邻的数 \(x\) 可以合并成一个数 \(x+1\),求最后剩下的数中最大的值

State

\(2<=n<=262144\)

\(1<=a[i]<=40\)

Input

4
1
1
1
2

Output

3

Solution

如果数据范围足够小题目完全可以区间 \(dp\);

发现这道题的值域很小,不妨可以利用 \(dp\) 来表示是否可以凑出 \(i\),并寻找 \(i\) 的最大值;

但只有一维是远远不够的,令 \(dp[i][j]\) 为区间 \([j,dp[i][j]]\) 可以合并为 \(i\),知道了 \(dp[i][j]\) 之后其实是很有用的,下一步就是如何 \(i->i+1\);

直接给出方程: \(dp[i+1][j]=dp[i][dp[i][j]+1]\)

这样一步步推下去,如果 \(dp[i][j]!=0\) 就可以知道最大的 \(i\) 是多少了


Code

const int N = 3e5 + 5;
 
    int n, m, k, _;
    int a[N];
    int dp[60][N];

signed main()
{
    // IOS;
    while(~ sd(n)){
        rep(i, 1, n) sd(a[i]);
        for(int i = 1; i <= n; i ++){
            dp[a[i]][i] = i;
        }
        int ans = 0;
        for(int i = 1; i <= 58; i ++){
            for(int j = 1; j <= n; j ++){
                if(dp[i - 1][j] && dp[i - 1][dp[i - 1][j] + 1])
                    dp[i][j] = dp[i - 1][dp[i - 1][j] + 1];
                if(dp[i][j])
                    ans = i;
            }
        }
        pd(ans);
    }
    // PAUSE;
    return 0;
}

标签:int,Solution,262144,State,USACO16OPEN,Input,dp,sd
来源: https://www.cnblogs.com/Segment-Tree/p/15376922.html