D. Recovering BST [区间dp]

题意:给出一个连续上升的序列 a a ,问能否构成一个任意两个相邻节点不互质的BST


题解:
区间 dp d p
使用 C[i][j] C [ i ] [ j ] 表示 [i,j] [ i , j ] 是否能够构成一颗合法的排序树
使用 L[i][j] L [ i ] [ j ] 表示以 j j 为根 [i,j1] [ i , j − 1 ] 能否构成一颗左子树
使用 R[i][j] R [ i ] [ j ] 表示以 i i 为根 [i+1,j] [ i + 1 , j ] 能否构成一颗右子树
中间枚举 k[l,r] k ∈ [ l , r ] 根,然后通过查找 a[l1] a [ l − 1 ] 是否与 k k 互质来判断能否由当前区间合法拓展到 [l1,r] [ l − 1 , r ] [l,r+1] [ l , r + 1 ] 合法


AC代码:

#include 
using namespace std;
typedef long long ll;
#define met(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define per(i, a, b) for(int i = a; i >= b; i--)
#define fi first
#define se second
#define pb push_back
const int maxn = 1e3 + 10;

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

int L[maxn][maxn], R[maxn][maxn];

bool C[maxn][maxn];

int main() {
    while(~scanf("%d", &n)) {
        met(C, false);
        met(L, 0); met(R, 0);
        met(g, 0);
        rep(i, 1, n) scanf("%d", &a[i]);
        rep(i, 1, n) rep(j, i+1, n) if(__gcd(a[i], a[j]) > 1) g[i][j] = g[j][i] = 1;
        rep(i, 1, n) L[i][i] = R[i][i] = 1, C[i][i] = true;
        int r;
        rep(len, 1, n) {
            for(int l = 1; (r = (l + len - 1)) <= n; l++) {
                rep(k, l, r) {
                    if(L[l][k] && R[k][r]) {
                        C[l][r] = true;
                        if(g[k][l - 1]) R[l - 1][r] = true;
                        if(g[k][r + 1]) L[l][r + 1] = true;
                    }
                }
            }
        }
        if(C[1][n]) puts("Yes");
        else puts("No");
    }
    return 0;
}

你可能感兴趣的:(codeforces,区间dp)