#include<iostream>

struct Node {
  int k;
  Node *left=nullptr;
  Node *right=nullptr;
  Node(int k) :k(k) {}
};

Node *root;
using namespace std;

void insert(int, Node *);
void insert(int k) {
  if (!root) {
    root = new Node(k);
  } else {
    insert(k, root);
  }
}

void insert(int k, Node *curr) {
  if (k < curr->k) {
    if (!curr->left) {
      curr->left = new Node(k);
    } else {
      insert(k, curr->left);
    }
  } else {
    if (!curr->right) {
      curr->right = new Node(k);
    } else {
      insert(k, curr->right);
    }
  }
}

bool find(int k, Node *curr, Node *& res, Node *& parent) {
  if (!curr) return false;
  if (curr->k == k) {
    res = curr;
  } else {
    parent = curr;
    if (k < curr->k) {
      return find(k, curr->left, res, parent);
    } else {
      return find(k, curr->right, res, parent);
    }
  }
  return true;
}

void remove(int k) {
  Node * target = nullptr;
  Node * parent = nullptr;
  find(k, root, target, parent);
  if (!target) return;  // don't contain the value we're removing
  bool deleting_root = !parent;  // true if we're deleting the root

  // Four cases: two children, left child only, right child only, no children
  // Case 1: Two children
  // In this case, we want to give the target its successor's key, then delete
  // the successor
  if (target->left and target->right) {
    auto successor = target->right;
    // Two subcases: 
    // - If target->right has no left child, the target's successor is target->right
    // - Otherwise, the target's successor is the farthest straight left descendant of target->right
    if (!successor->left) {
      target->k = successor->k;
      target->right = successor->right;
      delete successor;
    } else {
      auto successor_parent = successor;
      while (successor->left) {
        successor_parent = successor;
        successor = successor->left;
      }
      target->k = successor->k;
      successor_parent->left = nullptr;
      delete successor;
    }
  } else {  // In cases 2-4, we're replacing the target
    Node *replacement;
    // Case 2: Replacing the target with the target's left child
    if (target->left and not target->right) {
      replacement = target->left;
    } else if (target->right and not target->left) {
      replacement = target->right;
    } else {  // If the target has no children, 
              // we're replacing the target with nothing
      replacement = nullptr;
    }
    if (deleting_root) {
      root = replacement;
    } else {
      ((target == parent->left) ? (parent->left) : (parent->right)) = replacement;
    }
    delete target;
  }
}

void print_preorder(Node *curr) {
  if (!curr) return;
  std::cout << " " << curr->k;
  print_preorder(curr->left);
  print_preorder(curr->right);
}

void print_inorder(Node *curr) {
  if (!curr) return;
  print_inorder(curr->left);
  std::cout << " " << curr->k;
  print_inorder(curr->right);
}

int main() {
  string cmd;
  int n; cin >> n;
  while (cin >> cmd) {
    if (cmd == "insert") {
      cin >> n;
      insert(n);
    } else if (cmd == "find") {
      cin >> n;
      Node *p1 = nullptr;
      Node *p2 = nullptr;
      std::cout << (find(n, root, p1, p2) ? "yes" : "no") << std::endl;
    } else if (cmd == "delete") {
      cin >> n;
      remove(n);
    } else if (cmd == "print") {
      print_inorder(root); cout << endl;
      print_preorder(root); cout << endl;
    }
  }
}



Measured memory_bytes: 15516