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

    题意简述

    给定一棵(BST)的点数和点权,且满足相连的点的最小公约数都不为(1) ,问是否能还原 这棵(BST)的形态。

    Sol

    题目给出的点权序列是有序的,而且又是一棵(BST)所以对于区间([l,r])而言,这整个区间的点的父亲一定是(l-1)(r+1)

    (f[l][r][rt])为区间([l,r])能否以(rt)作为根节点,(rt in [l,r])

    (O(n^4))的状态转移就出来了~

    时间炸了空间炸了

    考虑更优的做法。设(f[i][j][0/1])为区间([i,j])能否以(i-1,j+1)作为根。

    枚举区间,根。

    如果区间([i,k])(i-1)为根且区间([k,j])能以([j+1])为根,说明这两棵树有合并的可能,考虑最终([i-1,j+1])这棵大树是以谁为根((i-1)(j+1))。

    再如果,(i-1)可以和(k)合并,那区间([i-1,k])就能以(j+1)为根。

    另一边同理。

    Code

    #include<bits/stdc++.h>
    #define N (710)
    using namespace std;
    int n,a[N],f[N][N][2];
    bool g[N][N];
    inline int read(){
    	int w=0;
    	char ch=getchar();
    	while(ch>'9'||ch<'0') ch=getchar();
    	while(ch>='0'&&ch<='9'){
    		w=(w<<3)+(w<<1)+(ch^48);
    		ch=getchar();
    	}
    	return w;
    }
    inline int mgcd(int a,int b){
    	if(!b) return a;
    	return mgcd(b,a%b);
    }
    int main(){
    	n=read();
    	for(int i=1;i<=n;i++) a[i]=read(),f[i][i][0]=f[i][i][1]=1;
    	for(int i=1;i<n;i++)
    		for(int j=i+1;j<=n;j++)
    			if(mgcd(a[i],a[j])!=1) g[i][j]=g[j][i]=1;//预处理能否合并
    	for(int len=1;len<=n;len++){
    		for(int i=1,j;i+len-1<=n;i++){
    			j=i+len-1;
    			for(int k=i;k<=j;k++){
    				if(f[i][k][0]&&f[k][j][1]){
    					if(i==1&&j==n){
    						puts("Yes");
    						return 0;
    					}
    					if(g[i-1][k]) f[i-1][j][1]=1;
    					if(g[k][j+1]) f[i][j+1][0]=1;
    				}
    			}
    		}
    	}
    	puts("No");
    	return 0;
    }
    

    完结撒花❀

  • 相关阅读:
    EPANET头文件解读系列4——EPANET2.H
    EPANET头文件解读系列3——TOOLKIT.H
    EPANET头文件解读系列2——ENUMSTXT.H
    EPANET头文件解读系列1——TEXT.H
    ENUMSTXT.H中的指针数组
    main函数的参数
    函数指针与指针函数
    FMDB源码阅读
    17个提升iOS开发效率的必用工具
    UIKit性能调优实战讲解
  • 原文地址:https://www.cnblogs.com/xxbbkk/p/14422365.html
Copyright © 2011-2022 走看看