给一个先序遍历序列,构建一个二叉树,在垂直方向上给二叉树分列,计算每一列的和。
开始我按照这个序列构建了一个二叉树,然后遍历进行计算,代码如下:

1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 5 const int maxn = 199; 6 const int mid = 100; 7 8 struct Node 9 { 10 int value; 11 Node *left, *right; 12 }; 13 14 Node * new_node() 15 { 16 Node * u = (Node *)malloc(sizeof(Node)); 17 if(u) 18 { 19 u->value = 0; 20 u->left = u->right = NULL; 21 } 22 return u; 23 } 24 25 int first; 26 27 int build(Node * u) 28 { 29 int x; 30 scanf("%d", &x); 31 //if the first data of the case is -1, return 0; 32 if(first) 33 { 34 first = 0; 35 if(x == -1) return 0; 36 } 37 u->value = x; 38 if(x > 0) 39 { 40 if(!u->left) u->left = new_node(); 41 build(u->left); 42 if(!u->right) u->right = new_node(); 43 build(u->right); 44 } 45 return 1; 46 } 47 48 void remove_tree(Node * u) 49 { 50 if(!u) return; 51 remove_tree(u->left); 52 remove_tree(u->right); 53 free(u); 54 } 55 56 int n, ans[maxn]; 57 int left, right; 58 59 void traversal(Node * p, int step) //preoder traversal 60 { 61 //step represent the displacement relative to root node 62 if(p->value > 0) 63 { 64 ans[mid+step] += p->value; 65 if(mid + step < left) left = mid + step; 66 if(mid + step >= right) right = mid + step + 1; 67 } 68 if(p->left) traversal(p->left, step-1); 69 if(p->right) traversal(p->right, step+1); 70 } 71 72 int main() 73 { 74 #ifdef LOCAL 75 freopen("in", "r", stdin); 76 #endif 77 int kase = 0; 78 while(1) 79 { 80 Node * root; 81 root = new_node(); 82 first = 1; 83 left = 100; 84 right = 101; 85 if(!build(root)) break; 86 Node * p = root; 87 memset(ans, 0, sizeof(ans)); 88 traversal(root, 0); 89 remove_tree(root); 90 printf("Case %d:\n", ++kase); 91 for(int i = left; i < right; i++) 92 { 93 printf("%s", i == left ? "" : " "); 94 printf("%d", ans[i]); 95 } 96 printf("\n\n"); 97 } 98 return 0; 99 } 100
后来有看了别人代码,忽然发现,既然这个序列是按先序遍历给的,就没有必要构建二叉树了,可以直接计算啊,又用递归写了一个,上面那个时间0.06s,这个0.052s,差别不是很大。代码如下:

1 #include <cstdio> 2 #include <cstring> 3 4 const int maxn = 199; 5 const int mid = 100; 6 int ans[maxn]; 7 int left, right; //the left and right boundary 8 int first; 9 10 int tree_dfs(int step) 11 { 12 int x; 13 scanf("%d", &x); 14 if(first) 15 { 16 first = 0; 17 if(x == -1) return 0; 18 } 19 if(x > 0) 20 { 21 ans[mid+step] += x; 22 if(mid + step < left) left = mid + step; 23 if(mid + step >= right) right = mid + step + 1; 24 tree_dfs(step-1); 25 tree_dfs(step+1); 26 } 27 return 1; 28 } 29 30 int main() 31 { 32 #ifdef LOCAL 33 freopen("in", "r", stdin); 34 #endif 35 int kase = 0; 36 while(1) 37 { 38 first = 1; 39 left = 100; 40 right = 101; 41 memset(ans, 0, sizeof(ans)); 42 if(!tree_dfs(0)) break; 43 printf("Case %d:\n", ++kase); 44 for(int i = left; i < right; i++) 45 { 46 printf("%s", i == left ? "" : " "); 47 printf("%d", ans[i]); 48 } 49 printf("\n\n"); 50 } 51 return 0; 52 }
刚开始没注意结果不会超过80个,以为是数据输出的要求,超过80要换行呢,开了一个大数组,对边界各种处理,最后还WA了,唉,怎么总感觉读不懂题目呢 ...