MZOJ
类似于区间动归
中序遍历:先遍历左儿子,再遍历根节点,最后遍历右儿子
盗用百科一张图
中序遍历的结果:
D − B − E − A − C − F D-B-E-A-C-F D−B−E−A−C−F
本题思路:
如能够构成一棵中序遍历的树,则在序列中一定存在一个
i
i
i的前面数是
i
i
i的左儿子,
i
i
i后面的数构成
i
i
i的右儿子
举例:在上述 D − B − E − A − C − F D-B-E-A-C-F D−B−E−A−C−F中,若 A A A为根,则 A A A的前面 D , B , E D,B,E D,B,E构成 A A A的左儿子, A A A的后面构成右儿子
所以 l [ i ] [ j ] l[i][j] l[i][j]表示在区间 i i i到 j j j中,表示区间 [ i , j ] [i,j] [i,j] 是否可以作为 j j j的左儿子,即 l [ i ] [ j ] l[i][j] l[i][j]表示以 j j j为根 [ i , j − 1 ] [i,j-1] [i,j−1]为左子树是否合法。 r [ i ] [ j ] r[i][j] r[i][j]表示在区间 [ i , j ] [i,j] [i,j]是否可以作为 i i i的右儿子,即 r [ i ] [ j ] r[i][j] r[i][j]表示以 i i i为根 [ i + 1 , j ] [i+1,j] [i+1,j]为右子树是否合法
b i a n [ i ] [ j ] bian[i][j] bian[i][j]表示 i , j i,j i,j两个点是否能相连,因为不能互质
枚举每个转移点,方程:
if(bian[k][j] && l[i][k] && r[k][j-1])
l[i][j]=true;
if(bian[k][i] && l[i+1][k] && r[k][j])
r[i][j]=true;
Code
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(register int (i)=(a);(i)<=(b);(i)++)
#define don(i,a,b) for(register int (i)=(a);(i)>=(b);(i)--)
using namespace std;
const int maxn=1e5+10;
const int maxm=1e3+10;
int T,n;
int a[maxn];
int l[maxm][maxm],r[maxm][maxm],bian[maxm][maxm];
template <class t> inline void read(t &x) {
x=0;int f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();}
x*=f;
}
void work() {
rep(len,2,n) {
rep(i,1,n-len+1) {
int j=i+len-1;
rep(k,i,j) {
if(bian[k][j] && l[i][k] && r[k][j-1])
l[i][j]=true;
if(bian[k][i] && l[i+1][k] && r[k][j])
r[i][j]=true;
}
}
}
}
inline int gcd(int a,int b) {
if(b==0) return a;
else gcd(b,a%b);
}
void readdata() {
read(T);
while(T--) {
read(n);
memset(a,false,sizeof(a));
memset(bian,false,sizeof(bian));
memset(l,false,sizeof(l));
memset(r,false,sizeof(r));
rep(i,1,n) read(a[i]);
rep(i,1,n)
rep(j,i+1,n) {
//if(!gcd(a[i],a[j])) bian[i][j]=bian[j][i]=true;
bian[i][j] = bian[j][i] = (gcd(a[i], a[j]) != 1);
}
rep(i,1,n) l[i][i]=r[i][i]=true;
work();
bool flag=0;
rep(i,1,n) {
if(l[1][i] && r[i][n]) {
flag=true;
break;
}
}
if(flag) printf("Yes\n");
else printf("No\n");
}
}
int main() {
freopen("input.txt","r",stdin);
readdata();
return 0;
}