zoukankan      html  css  js  c++  java
  • [题解] [CF1025D] Recovering BST

    题面

    题解

    如果不是二叉搜索树其实这题就是最小生成树板子题
    (f[l][r][k])([l, r]) 这段区间是否可以以 (k) 为根构成一棵合法的树
    转移就是

    [f[l][r][k] |= f[l][mid][i] & f[mid + 1][r][j], mid in [l, r - 1] ]

    这个方程是 (O(n^5)) 的, 考虑优化
    考虑到这样一个性质, 我们还是以 ([l, r]) 中根为 (k) 为例
    我们只需要使 ([l, k - 1]) , ([k + 1, r]) 这两段区间可以构成合法的一棵树
    并且这两棵树的树根可以和 (k) 相连就可以了
    (g[l][r])([l, r]) 这一段区间是否可以以 (r) 为根构成一棵合法的树
    (h[l][r])([l, r]) 这一段区间是否可以以 (l) 为根构成一棵合法的树
    那么 (f[l][r][k] = 1) 就是 (g[l][k] = 1), (h[k][r] = 1)
    那么我们就将求 (f) 转化为了求 (g, h)
    (g) 的转移方程又是

    [g[l][r] |= g[l][k] & h[k][r - 1] ]

    (k)([l, r - 1]) 中且 (k) 可以与 (r) 连边
    (h) 的转移方程类似, 这里就不再赘述了
    那么这样答案就是 (O(n^3)) 的了
    答案合法只需要 ([1, n]) 中存在一个 (i) 使得 (g[1][i] = h[i][n] = 1)

    Code

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    const int N = 705; 
    using namespace std;
    
    int n, a[N];
    bool f[N][N], g[N][N], vis[N][N]; 
    
    template < typename T >
    inline T read()
    {
    	T x = 0, w = 1; char c = getchar();
    	while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return x * w; 
    }
    
    int gcd(int n, int m) { return m ? gcd(m, n % m) : n; }
    
    int main()
    {
    	n = read <int> ();
    	for(int i = 1; i <= n; i++)
    		a[i] = read <int> ();
    	for(int i = 1; i <= n; i++)
    		f[i][i] = g[i][i] = 1; 
    	for(int i = 1; i <= n; i++)
    		for(int j = 1; j <= n; j++)
    			if(i != j) vis[i][j] = gcd(a[i], a[j]) != 1; 
    	for(int r, k = 2; k <= n; k++)
    		for(int l = 1; l + k - 1 <= n; l++)
    		{
    			r = l + k - 1;
    			for(int p = l; p < r; p++)
    				if(vis[p][r]) f[l][r] |= f[l][p] & g[p][r - 1];
    			for(int p = r; p > l; p--)
    				if(vis[l][p]) g[l][r] |= f[l + 1][p] & g[p][r]; 
    		}
    	for(int i = 1; i <= n; i++)
    		if(f[1][i] & g[i][n]) { puts("Yes"); return 0; }
    	puts("No"); 
    	return 0; 
    }
    

    一点小小的收获

    有的时候可以把一个式子拆成两部分, 对两部分分开 DP
    因为拆开之后某一个值不需要再枚举了, 所以可以优化复杂度

  • 相关阅读:
    java多线程详解(1)-多线程入门
    有关java中的hashCode问题
    java自动装箱和自动拆箱注意细节
    jquery选择器
    win10专业版激活密钥
    python3小例子:scrapy+mysql
    java List 等份截取
    七大查找算法
    十大经典排序算法
    jQuery.extend()方法
  • 原文地址:https://www.cnblogs.com/ztlztl/p/12790643.html
Copyright © 2011-2022 走看看