• Solution -「CF 1025D」Recovering BST


    Description

    Link.

    给定一个升序序列,问是否存在一种方法使得这个升序序列构成一棵 BST 并使一边相连的两点点权互质。

    Solution

    根据 BST 的性质可知对于一棵以 (u) 为根的子树 ( ext{subtree}(u)) 对应原序列中的一段区间,于是对于一个区间 ([l,r]),如果我们选取 (k) 作为根,那么 ( ext{subtree}(u)) 的形态就固定下来了。

    (f(i,j,k)) 为区间 ([i,j]) 中以 (k) 为根是否能够构成一棵 BST。

    这不好,这很差,考虑怎么优化。

    观察发现 ([l,r]) 的父亲结点一定是 (l-1)(r+1),于是重新设 (f(i,j,0 ext{ or }1)) 表示区间 ([i,j-1]) 的父结点为 (j) 是否合法 / 区间 ([i+1,j]) 的父结点为 (i) 是否合法。

    转移即:

    [f(i-1,j,1)=f(i-1,j,1)vee f(i,k,0)wedge f(k,j,1)wedge(gcd(a_{i-1},a_{k}) eq1) \ f(i,j+1,0)=f(i,j+1,0)vee f(i,k,0)wedge f(k,j,1)wedge(gcd(a_{j+1},a_{k}) eq1) ]

    (k) 是区间 DP 的中间点。于是就可以做了,边界与答案显然。

    #include<bits/stdc++.h>
    #define f(i,j,k) (f[i][j][k])
    int n,a[710];
    bool f[710][710][2],flag[710][710];
    int GCD(int one,int ano)
    {
    	if(ano==0)	return one;
    	else	return GCD(ano,one%ano);
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)	scanf("%d",&a[i]);
    	for(int i=1;i<=n;++i)	f(i,i,1)=f(i,i,0)=1;
    	for(int i=1;i<=n;++i)
    	{
    		flag[i][0]=1;
    		for(int j=i;j<=n;++j)
    		{
    			flag[i][j]=flag[j][i]=(GCD(a[i],a[j])!=1);
    			flag[0][j]=1;
    		}
    	}
    	for(int i=n;i;--i)
    	{
    		for(int j=i;j<=n;++j)
    		{
    			for(int k=i;k<=j;++k)
    			{
    				f(i-1,j,1)|=(f(i,k,0)&f(k,j,1)&flag[i-1][k]);
    				f(i,j+1,0)|=(f(i,k,0)&f(k,j,1)&flag[j+1][k]);
    			}
    		}
    	}
    	printf((f(1,n,0)|f(1,n,1))?"Yes
    ":"No
    ");
    	return 0;
    }
    
  • 相关阅读:
    Spring-boot内置的程序管理监控工具-Actuator
    分表工具类(根据唯一字符串)
    ES设计及规范
    测试单元Junit一直进不去@test方法解决方案
    MAC OS怎样将普通成员升级为管理员
    elasticSearch小结
    Mysql 查询条件中字符串尾部有空格也能匹配上的问题
    gitlab进行meger代码回滚
    ES与关系型数据库的通俗比较
    kafka的生产者配置以及发送信息的三种方式
  • 原文地址:https://www.cnblogs.com/orchid-any/p/14631856.html
Copyright © 2020-2023  润新知