Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Reconstruction of a Tree

Write a program which reads two sequences of nodes obtained by the preorder tree walk and the inorder tree walk on a binary tree respectively, and prints a sequence of the nodes obtained by the postorder tree walk on the binary tree.

Input

In the first line, an integer $n$, which is the number of nodes in the binary tree, is given.

In the second line, the sequence of node IDs obtained by the preorder tree walk is given separated by space characters.

In the second line, the sequence of node IDs obtained by the inorder tree walk is given separated by space characters.

Every node has a unique ID from $1$ to $n$. Note that the root does not always correspond to $1$.

Output

Print the sequence of node IDs obtained by the postorder tree walk in a line. Put a single space character between adjacent IDs.

Constraints

$1 \leq n \leq 40$

Sample Input 1

5
1 2 3 4 5
3 2 4 1 5

Sample Output 1

3 4 2 5 1

Sample Input 2

4
1 2 3 4
1 2 3 4

Sample Output 2

4 3 2 1

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using static System.Math;

namespace CSharpSpiral {
	class Program {
		static void Main(string[] args) {
			var sw = new StreamWriter(Console.OpenStandardOutput()) {
				AutoFlush =
#if DEBUG
			true
#else
			false
#endif
			};
			Console.SetOut(sw);
			new Program().Solve(new ConsoleInput(
#if DEBUG
			new StreamReader("../../../inputData.txt")
#else
			Console.In
#endif
			, ' '));
			Console.Out.Flush();
		}
		public void Solve(ConsoleInput cin) {
			var N = cin.ReadInt;
			var Nodes = new BinaryNode<List<int>>[N];
			var Reveal = new BinaryNode<int>[N];
			for(int i = 0; i < N; i++) {
				Nodes[i] = new BinaryNode<List<int>> { Id = i };
				Reveal[i] = new BinaryNode<int> { Id = i };
			}
			var PreOrder = cin.ReadIntArray(N).Select(x => x - 1).ToArray();
			var InOrder = cin.ReadIntArray(N).Select(x => x - 1).ToArray();
			Reconstruct(Reveal, PreOrder, InOrder, 0, 0, N);
			Console.WriteLine(Reveal[PreOrder[0]].PostOrder().Select(x => x + 1).Join());
		}

		void Reconstruct(BinaryNode<int>[] Reveal, int[] PreOrder, int[] InOrder, int preStart, int inStart, int Length) {
			if(Length <= 1) return;
			var root = PreOrder[preStart];
			var partition = Array.FindIndex(InOrder, inStart, Length, s => s == root);
			var leftLength = partition - inStart;
			var rightLength = (Length - 1) - leftLength;
			var leftChildId = leftLength == 0 ? -1 : PreOrder[preStart + 1];
			var rightChildId = rightLength == 0 ? -1 : PreOrder[preStart + 1 + leftLength];
			Reveal[root].Adopt(
				leftLength == 0 ? null : Reveal[leftChildId], rightLength == 0 ? null : Reveal[rightChildId]);
			Reconstruct(Reveal, PreOrder, InOrder, preStart + 1, inStart, leftLength);
			Reconstruct(Reveal, PreOrder, InOrder, preStart + 1 + leftLength, partition + 1, rightLength);
		}

		class TreeNode<T> {
			public virtual TreeNode<T> Parent { get; set; }
			public T Value { get; set; }
			public int Id { get; set; }
			public int Order { get; set; }
			public virtual List<TreeNode<T>> Children { get; set; } = new List<TreeNode<T>>();
			public virtual bool isRoot { get { return Parent == null; } }
			public virtual bool isLeaf { get { return !Children.Any(); } }
			public bool isInternal { get { return !isRoot && !isLeaf; } }
			public virtual int Depth {
				get {
					var count = 0;
					var P = this;
					while(!P.isRoot) {
						P = P.Parent;
						count++;
					}
					return count;
				}
			}
			public int Height {
				get {
					if(isLeaf) return 0;
					return Children.Select(X => X.Height).Max() + 1;
				}
			}
			public virtual int Degree { get { return Children.Count(); } }

			public void AdoptMany(List<TreeNode<T>> children) {
				Children = children;
				foreach(var node in children)
					node.Parent = this;
			}
			public void AdoptMany(TreeNode<T>[] Base, IEnumerable<int> call) {
				var children = call.Select(k => Base[k]).ToList();
				AdoptMany(children);
			}
			public void Adopt(TreeNode<T> child) {
				Children.Add(child);
				child.Parent = this;
			}
		}
		class BinaryNode<T>: TreeNode<T> {
			public new BinaryNode<T> Parent { get; set; }
			public BinaryNode<T> Left { get; set; }
			public BinaryNode<T> Right { get; set; }
			public new List<BinaryNode<T>> Children {
				get { return new BinaryNode<T>[] { Left, Right }.Where(x => x != null).ToList(); }
			}
			public override int Depth {
				get {
					var count = 0;
					var P = this;
					while(!P.isRoot) {
						P = P.Parent;
						count++;
					}
					return count;
				}
			}
			public new bool isRoot { get { return Parent == null; } }
			public override bool isLeaf { get { return Left == null && Right == null; } }
			public override int Degree {
				get { return (Left != null ? 1 : 0) + (Right != null ? 1 : 0); }
			}
			public void Adopt(BinaryNode<T> left, BinaryNode<T> right) {
				Left = left; Right = right;
				if(left != null) left.Parent = this; if(right != null) right.Parent = this;
			}
			public BinaryNode<T> Sibling {
				get { return isRoot ? null : Equals(Parent.Left) ? Parent.Right : Parent.Left; }
			}
			public static void GetHeight(BinaryNode<T>[] Nodes, out int[] Res) {
				Res = new int[Nodes.Length];
				foreach(var root in Nodes.Where(n => n.isRoot)) {
					GetHeight(root, Res);
				}
			}
			private static void GetHeight(BinaryNode<T> now, int[] Res) {
				if(now.isLeaf || !now.Children.Any()) { Res[now.Id] = 0; return; }
				foreach(var child in now.Children) {
					GetHeight(child, Res);
				}
				Res[now.Id] = now.Children.Max(c => Res[c.Id]) + 1;
			}
			private static void DFS(BinaryNode<T> now,
				Action<BinaryNode<T>> OnEnter,
				Action<BinaryNode<T>> OnMiddle,
				Action<BinaryNode<T>> OnLeave
			) {
				if(now == null) return;
				OnEnter?.Invoke(now);
				DFS(now.Left, OnEnter, OnMiddle, OnLeave);
				OnMiddle?.Invoke(now);
				DFS(now.Right, OnEnter, OnMiddle, OnLeave);
				OnLeave?.Invoke(now);
			}
			public void PreLabel() {
				var count = 0;
				DFS(this, b => b.Order = count++, null, null);
			}
			public void InLabel() {
				var count = 0;
				DFS(this, null, b => b.Order = count++, null);
			}
			public void PostLabel() {
				var count = 0;
				DFS(this, null, null, b => b.Order = count++);
			}
			public List<int> PreOrder() {
				var order = new List<int>();
				DFS(this, b => order.Add(b.Id), null, null);
				return order;
			}
			public List<int> InOrder() {
				var order = new List<int>();
				DFS(this, null, b => order.Add(b.Id), null);
				return order;
			}
			public List<int> PostOrder() {
				var order = new List<int>();
				DFS(this, null, null, b => order.Add(b.Id));
				return order;
			}
		}
	}
	static class ExtendClass {
		public static void Swap<T>(this T[] A, int x, int y) {
			var tmp = A[x];
			A[x] = A[y];
			A[y] = tmp;
		}
		public static string Join<T>(this IEnumerable<T> X, string separator = " ") => string.Join(separator, X);
	}
	class ConsoleInput {
		private readonly TextReader _stream;
		private readonly char _separator = ' ';
		private readonly Queue<string> inputStream;
		public ConsoleInput(TextReader stream, char separator = ' ') {
			this._separator = separator;
			this._stream = stream;
			inputStream = new Queue<string>();
		}
		public string Read {
			get {
				if(inputStream.Count != 0) return inputStream.Dequeue();
				string[] tmp = _stream.ReadLine().Split(_separator);
				for(int i = 0; i < tmp.Length; ++i)
					inputStream.Enqueue(tmp[i]);
				return inputStream.Dequeue();
			}
		}
		public string ReadLine { get { return _stream.ReadLine(); } }
		public int ReadInt { get { return int.Parse(Read); } }
		public long ReadLong { get { return long.Parse(Read); } }
		public double ReadDouble { get { return double.Parse(Read); } }
		public string[] ReadStrArray(long N) {
			var ret = new string[N];
			for(long i = 0; i < N; ++i)
				ret[i] = Read;
			return ret;
		}
		public int[] ReadIntArray(long N) { var ret = new int[N]; for(long i = 0; i < N; ++i) ret[i] = ReadInt; return ret; }
		public long[] ReadLongArray(long N) { var ret = new long[N]; for(long i = 0; i < N; ++i) ret[i] = ReadLong; return ret; }
		public double[] ReadDoubleArray(long N) { var ret = new double[N]; for(long i = 0; i < N; ++i) ret[i] = ReadDouble; return ret; }
		public bool isEOF {
			get { return _stream.Peek() == -1; }
		}
	}

}