zoukankan      html  css  js  c++  java
  • Codeforces Round #505 D. Recovering BST(区间DP)

    首先膜一发网上的题解。大佬们tql。

    给你n个单调递增的数字,问是否能够把这些数字重新构成一棵二叉搜索树(BST),且所有的父亲结点和叶子结点之间的gcd > 1?

    这个题场上是想暴力试试的。结果不行。发现符合最优子结构,可以DP。但是想不出来怎么转移。

    看了大佬的题解。

    若以第 k 个结点为根节点,用 L[i][k] 表示是否能够向左延伸到 i 点,R[k][j] 表示是否能够向右延伸到 j 点。

    那么区间 [l, r] 合法,仅当 L[l][k] && R[k][r] == 1。

    这样有了断点 k 作为[l, r]的根,就可以判断gcd能否用L[l][r] 和 R[l][r] 更新 R[l-1][r] 和 L[l][r+1]。

    判断gcd可以预处理。

    这样总复杂度是n^2 * logn

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <iostream>
    using namespace std;
    typedef long long LL;
    const int maxn = 700 + 10;
    
    int n;
    int a[maxn];
    int v[maxn][maxn], L[maxn][maxn], R[maxn][maxn], C[maxn][maxn];
    int dp[maxn][maxn][2];
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
        {
            L[i][i] = R[i][i] = 1;
            scanf("%d", &a[i]);
        }
    
        for (int i = 1; i <= n; i++)
        for (int j = i+1; j <= n; j++)
            v[i][j] = v[j][i] = __gcd(a[i], a[j]) != 1;
    
        int r;
        for (int len = 1; len <= n; len++)
        for (int l = 1; (r = l+len-1) <= n; l++)
        for (int k = l; k <= r; k++)
            if (L[l][k] && R[k][r])
            {
                C[l][r] = 1;
                if (v[k][l-1]) R[l-1][r] = 1;
                if (v[k][r+1]) L[l][r+1] = 1;
            }
    
        printf("%s
    ", C[1][n]?"Yes" : "No");
    }
  • 相关阅读:
    歌词:青春
    转载:只输了五元钱
    极静之渊

    低学翁
    心灵死化,何时巨变?
    无题

    意念
    爱之切
  • 原文地址:https://www.cnblogs.com/ruthank/p/9514745.html
Copyright © 2011-2022 走看看