CF1025D Recovering BST
题意:给定序列,问能否将其构成一颗BST,使得所有gcd(x, fa[x]) > 1
解:看起来是区间DP但是普通的f[l][r]表示不了根,f[l][r][root]又是n4的会超时,怎么办?
看了题解发现惊为天人......
f_l[l][r]表示[l, r]能否构成l-1的右子树,f_r[l][r]表示[l, r]能否构成r+1的左子树。
然后我们就发现这个神奇的东西变成n3了......
1 #include <cstdio> 2 3 const int N = 710; 4 5 int gcd(int ta, int tb) { 6 if(!tb) { 7 return ta; 8 } 9 return gcd(tb, ta % tb); 10 } 11 12 inline void read(int &x) { 13 x = 0; 14 char c = getchar(); 15 while(c < '0' || c > '9') { 16 c = getchar(); 17 } 18 while(c >= '0' && c <= '9') { 19 x = (x << 3) + (x << 1) + c - 48; 20 c = getchar(); 21 } 22 return; 23 } 24 25 int a[N]; 26 bool G[N][N], val[N][N], var[N][N]; 27 28 int main() { 29 int n; 30 read(n); 31 for(int i = 1; i <= n; i++) { 32 read(a[i]); 33 } 34 35 for(int i = 1; i <= n; i++) { 36 for(int j = i; j <= n; j++) { 37 G[i][j] = G[j][i] = (gcd(a[i], a[j]) > 1); 38 } 39 } 40 for(int i = 1; i <= n; i++) { 41 if(i > 1) { 42 val[i][i] = G[i][i - 1]; 43 } 44 if(i < n) { 45 var[i][i] = G[i][i + 1]; 46 } 47 } 48 49 for(int len = 2; len < n; len++) { 50 for(int l = 1; l + len - 1 <= n; l++) { 51 int r = l + len - 1; 52 for(int k = l; k <= r; k++) { // root 53 bool t = (k == l ? 1 : var[l][k - 1]) & (k == r ? 1 : val[k + 1][r]); 54 if(!t) { 55 continue; 56 } 57 if(G[k][r + 1]) { 58 var[l][r] = 1; 59 } 60 if(G[k][l - 1]) { 61 val[l][r] = 1; 62 } 63 } 64 } 65 } 66 67 for(int i = 1; i <= n; i++) { 68 bool t = (i == 1 ? 1 : var[1][i - 1]) & (i == n ? 1 : val[i + 1][n]); 69 if(t) { 70 printf("Yes"); 71 return 0; 72 } 73 } 74 printf("No"); 75 return 0; 76 }