Problem:
Binary Search Tree II

Write a program which performs the following operations to a binary search tree $T$ by adding the find operation to A: Binary Search Tree I.

insert $k$: Insert a node containing $k$ as key into $T$.

find $k$: Report whether $T$ has a node containing $k$.

print: Print the keys of the binary search tree by inorder tree walk and preorder tree walk respectively.

Input

In the first line, the number of operations $m$ is given. In the following $m$ lines, operations represented by insert $k$, find $k$ or print are given.

Output

For each find $k$ operation, print "yes" if $T$ has a node containing $k$, "no" if not.

In addition, for each print operation, print a list of keys obtained by inorder tree walk and preorder tree walk in a line respectively. Put a space character before each key.

Constraints

The number of operations $\leq 500,000$

The number of print operations $\leq 10$.

$-2,000,000,000 \leq key \leq 2,000,000,000$

The height of the binary tree does not exceed 100 if you employ the above pseudo code.

The keys in the binary search tree are all different.

Sample Input 1

10
insert 30
insert 88
insert 12
insert 1
insert 20
find 12
insert 17
insert 25
find 16
print

Sample Output 1

yes
no
1 12 17 20 25 30 88
30 12 1 20 17 25 88

Reference

Introduction to Algorithms, Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. The MIT Press.

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;

namespace ALDS1_8_B
{
    class Program
    {
        static void Main(string[] args)
        {
            string line;
            // int[] vals;

            //入力
            line = Console.ReadLine().Trim();
            var commandCount = int.Parse(line);

            var nodes = new Nodes<int>();

            for (int i = 0; i < commandCount; i++)
            {
                line = Console.ReadLine().Trim();
                var vals = line.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToArray();
                if (vals[0] == "insert")
                {
                    nodes.Insert(int.Parse(vals[1]));
                }
                else if (vals[0] == "find")
                {
                    var n = nodes.Find(int.Parse(vals[1]));
                    Console.WriteLine((n != null ? "yes" : "no"));
                }
                else
                {
                    Console.WriteLine(" " + String.Join(" ", nodes.Inorder().Select(x => x.Value).ToArray()));
                    Console.WriteLine(" " + String.Join(" ", nodes.Preorder().Select(x => x.Value).ToArray()));
                }

            }
        }
    }

    public class Nodes<T> where T : IComparable<T>
    {
        private Node Root { get; set; } = null;

        public void Insert(T val)
        {
            Node y = null;
            Node z = new Node() { Value = val };
            Node x = Root;
            while (x != null)
            {
                y = x;
                if (x.Value.CompareTo(z.Value) > 0) x = x.Left;
                else if (x.Value.CompareTo(z.Value) < 0) x = x.Right;
                else break;
            }
            z.Parent = y;
            if (y == null)
            {
                Root = z;
            }
            else if (z.Value.CompareTo(y.Value) < 0)
            {
                y.Left = z; // z を y の左の子にする
            }
            else
            {
                y.Right = z; // z を y の右の子にする
            }
        }

        public Node Find(T val)
        {
            var n = Root;
            while (n != null)
            {
                if (n.Value.CompareTo(val) > 0) n = n.Left;
                else if (n.Value.CompareTo(val) < 0) n = n.Right;
                else break;
            }
            return n;
        }

        public IEnumerable<Node> Preorder(Node node = null)
        {
            if (Root == null)
                yield break;
            if (node == null)
                node = Root;

            yield return node;
            foreach (var child in node.Children())
            {
                foreach (var grandChild in Preorder(child))
                    yield return grandChild;
            }
        }

        public IEnumerable<Node> Inorder(Node node = null)
        {
            if (Root == null)
                yield break;
            if (node == null)
                node = Root;

            if (node.Left != null)
            {
                foreach (var grandChild in Inorder(node.Left))
                    yield return grandChild;
            }
            yield return node;
            if (node.Right != null)
            {
                foreach (var grandChild in Inorder(node.Right))
                    yield return grandChild;
            }
        }

        public IEnumerable<Node> Postorder(Node node = null)
        {
            if (Root == null)
                yield break;
            if (node == null)
                node = Root;

            foreach (var child in node.Children())
            {
                foreach (var grandChild in Postorder(child))
                    yield return grandChild;
            }
            yield return node;
        }

        public class Node
        {
            public T Value { get; set; }
            public Node Parent { get; set; }
            public Node Left { get; set; }
            public Node Right { get; set; }

            public string GetNodeType()
            {
                if (Parent == null) return "root";
                if (Left != null || Right != null) return "internal node";
                return "leaf";

            }

            public int GetDepth()
            {
                if (Parent == null) return 0;
                return Parent.GetDepth() + 1;
            }

            public IEnumerable<Node> Children()
            {
                if (Left != null) yield return Left;
                if (Right != null) yield return Right;
            }

        }
    }
}