区间dp——cf1025D二叉搜索树的中序遍历好题!

这题帮我复习了一下BST的中序遍历。。

因为给定的数组是递增的,那么BST的中序遍历一定是1 2 3 4 5 6 7 8 9 ... n

即[l,r]为左子树,那么根节点就是r+1,反之根节点就是l-1

那么我们只要枚举每个区间[l,r],再枚举[l,r]的根k,然后看l-1,r+1是否可以作为k的父亲。以此来扩展dp状态

L[l.r] | R[l,r]表示区间[l,r]的根是 l | r 是否可行

那么显然就是一个三重区间dp

#include<bits/stdc++.h>
using namespace std;
#define maxn 705

int n,a[maxn],g[maxn][maxn],L[maxn][maxn],R[maxn][maxn];

int main(){
    cin>>n;for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            g[i][j]=__gcd(a[i],a[j]);
            
    for(int i=1;i<=n;i++)L[i][i]=R[i][i]=1;
    for(int len=1;len<=n;len++)
        for(int l=1;l+len-1<=n;l++){
            int r=l+len-1;
            for(int k=l;k<=r;k++)//以k作为根节点 
                if(L[l][k] && R[k][r]){
                    if(l==1 && r==n){
                        puts("Yes");
                        return 0;
                    }
                    if(g[l-1][k]>1)R[l-1][r]=1;//[l,r]作为l-1的右儿子 
                    if(g[k][r+1]>1)L[l][r+1]=1;//[l,r]作为r+1的左儿子- 
                }
        }
    puts("No");
}
原文地址:https://www.cnblogs.com/zsben991126/p/10818827.html