CF 1025D:Recovering BST

CF 1025D:Recovering BST

题目直达

题意:

BST树:
节点结构:每个节点包含一个键值(key)、一个左子树指针和一个右子树指针。
左子树:对于每个节点,左子树中的所有节点的键值都小于该节点的键值。
右子树:对于每个节点,右子树中的所有节点的键值都大于该节点的键值。
无重复键:通常情况下,BST 中不允许有重复的键值。
现在有 n 个数,问是否能形成一个BSt树,其中每相邻的两个点不互质

思路(类比归并排序):

我们定义:dp[i][j][0/1] 表示区间 l - r 以(l-1)/(r+1)为根节点是否符合条件
我们枚举每一个点假定为根,再在被分开的两个区间内继续枚举子根,直到找到符合条件或者已经枚举完每一个点

具体见代码如下

#include<iostream>
#include<algorithm>
#include <cstring>

using namespace std;
int a[710];
bool g[710][710];
int dp[710][710][2];
int dfs(int l, int r, int k){
    if(l > r) return 1;
    if(dp[l][r][k] != -1) return dp[l][r][k];
    int x = k?r+1:l-1;
    for(int i = l;i <= r;i ++){
        if(!g[x][i]) continue;
        if(dfs(l, i - 1, 1) && dfs(i + 1, r, 0)) return dp[l][r][k] = 1;
    }
    return dp[l][r][k] = 0;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    memset(dp, -1, sizeof(dp));
    int n;
    cin >> n;
    for(int i = 1;i <= n;i ++) cin >> a[i];
    // 预处理存下互质的对(这里不存也是可以过的,n<=700)
    for(int i = 1;i <= n;i ++)
        for (int j = 1; j < i; j++){
            if (__gcd(a[i], a[j]) > 1){
                g[i][j] = true;
                g[j][i] = true;
            }
        }
    for(int i = 1;i <= n;i ++){
    //继续递归子区间,找符合条件的根
        if(dfs(1, i - 1, 1) && dfs(i + 1, n, 0)){
            cout << "Yes";
            return 0;
        }
    }
    cout << "No";
    return 0;
}
posted @ 2025-03-19 22:56  ter_rave  阅读(10)  评论(0)    收藏  举报