#include #include using namespace std; const int N_SIZE = 500010; const int DO_NOT_EXIST = -1; const int NOT_GIVEN = 0; const int INFINITE_DEPTH = 500010; const int PRIME_MODULUS = 999999937; int n; int pre_order[N_SIZE]; int post_order[N_SIZE]; int in_order[N_SIZE]; int index_in_pre_order[N_SIZE]; int index_in_post_order[N_SIZE]; int index_in_in_order[N_SIZE]; int given_nodes; int parent[N_SIZE]; int left_child[N_SIZE]; int right_child[N_SIZE]; int single_child[N_SIZE]; int subtree_size[N_SIZE]; int depth[N_SIZE]; int top_node; int top_node_leftmost_index; int single_lines; long long quantity; bool determinate[N_SIZE]; int pending; void construct_tree(int pre_order_start, int pre_order_end, int post_order_start, int post_order_end, int current_depth) { assert(pre_order_end - pre_order_start == post_order_end - post_order_start); int root = pre_order[pre_order_start]; subtree_size[root] = pre_order_end - pre_order_start + 1; depth[root] = current_depth; if (pre_order_start == pre_order_end) { left_child[root] = DO_NOT_EXIST; right_child[root] = DO_NOT_EXIST; single_child[root] = DO_NOT_EXIST; return; } assert(pre_order_start + 1 <= n); assert(post_order_end - 1 >= 1); if (pre_order[pre_order_start + 1] == post_order[post_order_end - 1]) { left_child[root] = DO_NOT_EXIST; right_child[root] = DO_NOT_EXIST; single_child[root] = pre_order[pre_order_start + 1]; parent[single_child[root]] = root; construct_tree(pre_order_start + 1, pre_order_end, post_order_start, post_order_end - 1, current_depth + 1); return; } left_child[root] = pre_order[pre_order_start + 1]; int left_subtree_length = index_in_post_order[left_child[root]] - post_order_start + 1; right_child[root] = pre_order[pre_order_start + left_subtree_length + 1]; single_child[root] = DO_NOT_EXIST; parent[left_child[root]] = root; parent[right_child[root]] = root; construct_tree(pre_order_start + 1, pre_order_start + left_subtree_length, post_order_start, post_order_start + left_subtree_length - 1, current_depth + 1); construct_tree(pre_order_start + left_subtree_length + 1, pre_order_end, post_order_start + left_subtree_length, post_order_end - 1, current_depth + 1); } void get_top_node() { int min_depth = INFINITE_DEPTH; top_node = DO_NOT_EXIST; for (int i = 1; i <= n; i++) { if (in_order[i] == 0) { continue; } if (min_depth > depth[in_order[i]]) { min_depth = depth[in_order[i]]; top_node = in_order[i]; } } } void top_node_to_root() { top_node_leftmost_index = 1; single_lines = 0; if (left_child[top_node] != DO_NOT_EXIST) { top_node_leftmost_index += subtree_size[left_child[top_node]]; } int current_node = top_node; int current_parent = parent[current_node]; while (current_parent != DO_NOT_EXIST) { if (right_child[current_parent] == current_node) { top_node_leftmost_index += subtree_size[left_child[current_parent]] + 1; } else if (single_child[current_parent] == current_node) { single_lines++; } current_node = current_parent; current_parent = parent[current_node]; } } void visit() { for (int i = 1; i <= n; i++) { determinate[i] = false; } int current_node = top_node; while (current_node != DO_NOT_EXIST) { determinate[current_node] = true; current_node = parent[current_node]; } for (int i = 1; i <= n; i++) { current_node = in_order[i]; if (current_node == DO_NOT_EXIST) { continue; } while (!determinate[current_node]) { determinate[current_node] = true; current_node = parent[current_node]; } } } void calculate_pending() { pending = 0; for (int i = 1; i <= n; i++) { if (single_child[i] != DO_NOT_EXIST && !determinate[i]) { pending++; } } } long long power(long long a, long long b, long long p) { long long result = 1; a = a % p; while (b > 0) { if (b % 2 == 1) { result = (result * a) % p; } b = b / 2; a = (a * a) % p; } return result; } long long mod_inverse(long long a, long long p) { return power(a, p - 2, p); } long long combination(long long a, long long b, long long p) { if (a < 0 || b > a || b < 0) { return 0; } long long result = 1; for (int i = 1; i <= b; i++) { result = result * (a - i + 1) % p; result = result * mod_inverse(i, p) % p; } return result; } void calculate_quantity(long long p) { quantity = power(2, pending, p); if (given_nodes == 0) { return; } assert(top_node != DO_NOT_EXIST); int top_index = index_in_in_order[top_node]; long long candidate1 = single_lines; long long chosen1 = top_index - top_node_leftmost_index; long long candidate2 = -1; long long chosen2 = top_index - top_node_leftmost_index; if (left_child[top_node] != DO_NOT_EXIST) { ; } else if (single_child[top_node] != DO_NOT_EXIST) { if (top_index < n && in_order[top_index + 1] != NOT_GIVEN) { ; } else if (top_index > 1 && in_order[top_index - 1] != NOT_GIVEN) { chosen1 -= subtree_size[single_child[top_node]]; } else { assert(given_nodes == 1); candidate2 = single_lines; chosen2 -= subtree_size[single_child[top_node]]; } } else { ; } long long above_top_node = (combination(candidate1, chosen1, p) + combination(candidate2, chosen2, p)) % p; quantity = quantity * above_top_node % p; } int main() { ios_base::sync_with_stdio(false); cin>>n; for (int i = 1; i <= n; i++) { cin>>pre_order[i]; index_in_pre_order[pre_order[i]] = i; } for (int i = 1; i <= n; i++) { cin>>post_order[i]; index_in_post_order[post_order[i]] = i; } given_nodes = 0; for (int i = 1; i <= n; i++) { cin>>in_order[i]; index_in_in_order[in_order[i]] = i; if (in_order[i] != NOT_GIVEN) { given_nodes++; } } parent[pre_order[1]] = DO_NOT_EXIST; construct_tree(1, n, 1, n, 1); get_top_node(); if (top_node != DO_NOT_EXIST) { top_node_to_root(); } visit(); calculate_pending(); calculate_quantity(PRIME_MODULUS); cout<