Loading

【题解】ABC252G - Pre-Order

题意

给定一个 \(1\)\(N\) 的排列 \(P\),求 dfs 序为 \(P\) 且以 \(1\) 为根的有根树的数量(答案模 \(998244353\)

注意对于有多个子结点的结点,按编号从小到大遍历子结点。

\(2 \leq N \leq 500\)

思路

区间 dp。

考虑设 \(dp[l][r]\) 为以 \(P_l\)\(P_r\) 组成,dfs 序为 \([P_l, P_r]\) 且以 \(P_l\) 为根的有根树数量。容易想到枚举最后遍历的子树区间 \([s, t]\),但是题目要求按编号升序遍历,因此难以判断合法性。

容易看到答案是 使 \([s, t]\) 添加后 dfs 序不变的有根树数量 $\times $ \([s, t]\) 组成的有根树数量。不妨考虑另外维护 \(dp^{\prime}[l][r]\) 表示将 \(P_{r + 1}\) 添加到以 \(P_l\) 为根,由 \([P_l, P_r]\) 组成的有根树后 dfs 序为 \([P_l, P_{r + 1}]\) 的方案数。易得:

\(dp[l, r] = \sum\limits_{l \leq k < r} dp^{\prime}[l][k] \times dp[k + 1][r]\)

$dp^{\prime}[l, r] = \sum\limits_{l \leq k < r, P_{k + 1} < P_{r + 1}} dp^{\prime}[l][k] \times dp[k + 1][r] $

边界条件是 \(dp[l][l] = dp^{\prime}[l][l] = 1\)

时间复杂度 \(O(n^3)\)

代码

#include <cstdio>
using namespace std;

const int maxn = 505;
const int mod = 998244353;

int n;
int p[maxn];
int dp[maxn][maxn][2];

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &p[i]);
        dp[i][i][0] = dp[i][i][1] = 1;
    }
    for (int l = 2; l <= n; l++)
    {
        for (int i = 1; i + l - 1 <= n; i++)
        {
            int j = i + l - 1;
            for (int k = i; k <= j - 1; k++)
            {
                dp[i][j][0] = (dp[i][j][0] + (1ll * dp[i][k][1] * dp[k + 1][j][0])) % mod;
                if (p[k + 1] < p[j + 1]) dp[i][j][1] = (dp[i][j][1] + (1ll * dp[i][k][1] * dp[k + 1][j][0])) % mod;
            }
        }
    }
    printf("%d\n", dp[1][n][0]);
    return 0;
}
posted @ 2022-05-23 18:48  kymru  阅读(81)  评论(0编辑  收藏  举报