题解:Luogu_P3147 [USACO16OPEN] 262144 P

题解:Luogu_P3147 [USACO16OPEN] 262144 P

Luogu_P3147 [USACO16OPEN] 262144 P
倍增DP

Solution

考虑这种合并区间的问题使用区间 DP,但 n 的范围太大没法设 fi,j 表示将 ij 合并为多少。

注意到能合并出的数最多为 58(40+log(262144)),于是我们将记录左右端点存值变为记录左端点和值存右端点。

状态:fi,j 表示以 i 为左端点,合并为 j 的区间右端点下标+1(方便转移)

边界:fi,a[i]=i+1

转移:fi,j=ffi,j1,j1(有点像倍增)

Code

//P3147

#include <iostream>
#include <cstdio>

using namespace std;

int read()
{
    int val = 0;
    bool si = 0;
    char ch = getchar();
    for (; !isdigit(ch); ch = getchar())
        si ^= ch == '-';
    for (;  isdigit(ch); ch = getchar())
        val = (val << 3) + (val << 1) + (ch ^ 48);
    return si ? - val : val;
}

const int N = 262145;

int n, ans, f[N][60];

int main()
{
    n = read();
    for (int i = 1; i <= n; i ++)
        f[i][read()] = i + 1;
    for (int j = 2; j <= 58; j ++)    
        for (int i = 1; i <= n; i ++)
        {
            if (f[i][j] == 0)
                f[i][j] = f[f[i][j - 1]][j - 1];
            if (f[i][j] != 0)
                ans = j;
        }
    printf("%d\n", ans);

    return 0;
}
posted @   nueryim  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示