Natasha travels around Mars in the Mars rover. But suddenly it broke down, namely — the logical scheme inside it. The scheme is an undirected tree (connected acyclic graph) with a root in the vertex 1, in which every leaf (excluding root) is an input, and all other vertices are logical elements, including the root, which is output. One bit is fed to each input. One bit is returned at the output.

There are four types of logical elements: [AND](https://en.wikipedia.org/wiki/Logical_conjunction) (2 inputs), [OR](https://en.wikipedia.org/wiki/Logical_disjunction) (2 inputs), [XOR](https://en.wikipedia.org/wiki/Exclusive_or) (2 inputs), [NOT](https://en.wikipedia.org/wiki/Negation) (1 input). Logical elements take values from their direct descendants (inputs) and return the result of the function they perform. Natasha knows the logical scheme of the Mars rover, as well as the fact that only one input is broken. In order to fix the Mars rover, she needs to change the value on this input.

For each input, determine what the output will be if Natasha changes this input.

Input

The first line contains a single integer n (2 ≤ n ≤ 10^6) — the number of vertices in the graph (both inputs and elements).

The i-th of the next n lines contains a description of i-th vertex: the first word "AND", "OR", "XOR", "NOT" or "IN" (means the input of the scheme) is the vertex type. If this vertex is "IN", then the value of this input follows (0 or 1), otherwise follow the indices of input vertices of this element: "AND", "OR", "XOR" have 2 inputs, whereas "NOT" has 1 input. The vertices are numbered from one.

It is guaranteed that input data contains a correct logical scheme with an output produced by the vertex 1.

Output

Print a string of characters '0' and '1' (without quotes) — answers to the problem for each input in the ascending order of their vertex indices.

Example

Input

10
AND 9 4
IN 1
IN 1
XOR 6 5
AND 3 7
IN 0
NOT 10
IN 1
IN 1
AND 2 8


Output

10110

Note

The original scheme from the example (before the input is changed):

<image>

Green indicates bits '1', yellow indicates bits '0'.

If Natasha changes the input bit 2 to 0, then the output will be 1.

If Natasha changes the input bit 3 to 0, then the output will be 0.

If Natasha changes the input bit 6 to 1, then the output will be 1.

If Natasha changes the input bit 8 to 0, then the output will be 1.

If Natasha changes the input bit 9 to 0, then the output will be 0.
#include <bits/stdc++.h>
using namespace std;
const int INFL = (int)1e9;
const long long int INFLL = (long long int)1e18;
const double INFD = numeric_limits<double>::infinity();
const double PI = 3.14159265358979323846;
bool nearlyeq(double x, double y) { return abs(x - y) < 1e-9; }
bool inrange(int x, int t) { return x >= 0 && x < t; }
long long int rndf(double x) {
  return (long long int)(x + (x >= 0 ? 0.5 : -0.5));
}
long long int floorsqrt(double x) {
  long long int m = (long long int)sqrt(x);
  return m + (m * m <= (long long int)(x) ? 0 : -1);
}
long long int ceilsqrt(double x) {
  long long int m = (long long int)sqrt(x);
  return m + ((long long int)x <= m * m ? 0 : 1);
}
long long int rnddiv(long long int a, long long int b) {
  return (a / b + (a % b * 2 >= b ? 1 : 0));
}
long long int ceildiv(long long int a, long long int b) {
  return (a / b + (a % b == 0 ? 0 : 1));
}
long long int gcd(long long int m, long long int n) {
  if (n == 0)
    return m;
  else
    return gcd(n, m % n);
}
long long int lcm(long long int m, long long int n) {
  return m * n / gcd(m, n);
}
enum op_t { IN, NOT, AND, OR, XOR };
struct val_t {
  op_t op;
  array<int, 5> x, y;
};
int neg(int x) { return x ^ 1; }
template <class nodeval_t, class edgeval_t>
struct tree_t {
  int n;
  vector<pair<int, int>> edges;
  vector<nodeval_t> vals;
  vector<edgeval_t> costs;
};
template <class nodeval_t, class edgeval_t>
class Tree {
 private:
  struct node {
    int id;
    vector<int> childs;
    int parent = -1;
    int deg = -1;
    int eid = -1;
    int subtree_n = 1;
    nodeval_t val;
    edgeval_t cost;
    bool operator<(const node &another) const {
      return deg != another.deg ? deg < another.deg : id < another.id;
    }
  };
  struct edgeinfo {
    int eid;
    int to;
    edgeval_t cost;
  };
  int n;
  static const edgeval_t init_cost = 1;
  vector<vector<edgeinfo>> edges;
  void tree_construction() {
    leaves = {};
    queue<int> que;
    que.push(root);
    while (que.size()) {
      int a = que.front();
      que.pop();
      deg_order.push_back(a);
      if (a == Tree::root) nodes[a].deg = 0;
      int leaf_flag = true;
      for (int i = 0; i < (int)(edges[a].size()); i++) {
        int b = edges[a][i].to;
        if (nodes[b].deg != -1) {
          nodes[a].parent = b;
          nodes[a].eid = edges[a][i].eid;
          nodes[a].cost = edges[a][i].cost;
          nodes[a].deg = nodes[b].deg + 1;
        } else {
          leaf_flag = false;
          nodes[a].childs.push_back(b);
          que.push(b);
        }
      }
      if (leaf_flag) leaves.push_back(a);
    }
    for (int i = (int)(n)-1; i >= 0; i--) {
      int a = deg_order[i];
      for (int j = 0; j < (int)(nodes[a].childs.size()); j++) {
        int b = nodes[a].childs[j];
        nodes[a].subtree_n += nodes[b].subtree_n;
      }
    }
  }

 public:
  vector<node> nodes;
  vector<int> deg_order;
  vector<int> leaves;
  int root;
  Tree(tree_t<nodeval_t, edgeval_t> T, int root) {
    n = T.n;
    nodes.resize(n);
    for (int i = 0; i < (int)(n); i++) {
      nodes[i].id = i;
      nodes[i].val = T.vals[i];
      nodes[i].cost = init_cost;
    }
    edges.resize(n);
    for (int i = 0; i < (int)(n - 1); i++) {
      edges[T.edges[i].first].push_back(
          {i, T.edges[i].second,
           ((int)(T.costs.size()) > i ? T.costs[i] : init_cost)});
      edges[T.edges[i].second].push_back(
          {i, T.edges[i].first,
           ((int)(T.costs.size()) > i ? T.costs[i] : init_cost)});
    }
    Tree::root = root;
    tree_construction();
    return;
  }
  vector<int> solve() {
    for (int i = (int)(deg_order.size()) - 1; i >= 0; i--) {
      int a = deg_order[i];
      if (nodes[a].val.op == NOT) {
        int b = nodes[a].childs[0];
        nodes[a].val.x[0] = neg(nodes[b].val.x[0]);
        for (int j = 1; j <= (int)(nodes[b].val.x.size() - 1); j++) {
          int buf = nodes[b].val.x[j];
          if (buf == 0) {
            nodes[a].val.x[1] = neg(buf);
          } else if (buf == 1) {
            nodes[a].val.x[2] = neg(buf);
          }
        }
      } else if (nodes[a].val.op == AND) {
        int l = nodes[a].childs[0];
        int r = nodes[a].childs[1];
        nodes[a].val.x[0] = nodes[l].val.x[0] & nodes[r].val.x[0];
        for (int j = 1; j <= (int)(nodes[l].val.x.size() - 1); j++) {
          int buf = nodes[l].val.x[j];
          if (buf == 0) {
            nodes[a].val.x[1] = buf & nodes[r].val.x[0];
          } else if (buf == 1) {
            nodes[a].val.x[2] = buf & nodes[r].val.x[0];
          }
        }
        for (int j = 1; j <= (int)(nodes[r].val.x.size() - 1); j++) {
          int buf = nodes[r].val.x[j];
          if (buf == 0) {
            nodes[a].val.x[3] = nodes[l].val.x[0] & buf;
          } else if (buf == 1) {
            nodes[a].val.x[4] = nodes[l].val.x[0] & buf;
          }
        }
      } else if (nodes[a].val.op == OR) {
        int l = nodes[a].childs[0];
        int r = nodes[a].childs[1];
        nodes[a].val.x[0] = nodes[l].val.x[0] | nodes[r].val.x[0];
        for (int j = 1; j <= (int)(nodes[l].val.x.size() - 1); j++) {
          int buf = nodes[l].val.x[j];
          if (buf == 0) {
            nodes[a].val.x[1] = buf | nodes[r].val.x[0];
          } else if (buf == 1) {
            nodes[a].val.x[2] = buf | nodes[r].val.x[0];
          }
        }
        for (int j = 1; j <= (int)(nodes[r].val.x.size() - 1); j++) {
          int buf = nodes[r].val.x[j];
          if (buf == 0) {
            nodes[a].val.x[3] = nodes[l].val.x[0] | buf;
          } else if (buf == 1) {
            nodes[a].val.x[4] = nodes[l].val.x[0] | buf;
          }
        }
      } else if (nodes[a].val.op == XOR) {
        int l = nodes[a].childs[0];
        int r = nodes[a].childs[1];
        nodes[a].val.x[0] = nodes[l].val.x[0] ^ nodes[r].val.x[0];
        for (int j = 1; j <= (int)(nodes[l].val.x.size() - 1); j++) {
          int buf = nodes[l].val.x[j];
          if (buf == 0) {
            nodes[a].val.x[1] = buf ^ nodes[r].val.x[0];
          } else if (buf == 1) {
            nodes[a].val.x[2] = buf ^ nodes[r].val.x[0];
          }
        }
        for (int j = 1; j <= (int)(nodes[r].val.x.size() - 1); j++) {
          int buf = nodes[r].val.x[j];
          if (buf == 0) {
            nodes[a].val.x[3] = nodes[l].val.x[0] ^ buf;
          } else if (buf == 1) {
            nodes[a].val.x[4] = nodes[l].val.x[0] ^ buf;
          }
        }
      }
    }
    nodes[root].val.y = nodes[root].val.x;
    vector<int> ans(n, -1);
    for (int i = 0; i < (int)(deg_order.size()); i++) {
      int a = deg_order[i];
      if (nodes[a].val.op == IN) {
        ans[a] = nodes[a].val.y[1];
      } else if (nodes[a].val.op == NOT) {
        int b = nodes[a].childs[0];
        for (int i = 1; i <= (int)(nodes[b].val.x.size() - 1); i++) {
          if (nodes[b].val.x[i] == -1) continue;
          int ibuf = (nodes[b].val.x[i] == 0 ? 1 : 2);
          nodes[b].val.y[i] = nodes[a].val.y[ibuf];
        }
      } else {
        int l = nodes[a].childs[0];
        int r = nodes[a].childs[1];
        for (int i = 1; i <= (int)(nodes[l].val.x.size() - 1); i++) {
          if (nodes[l].val.x[i] == -1) continue;
          int ibuf = (nodes[l].val.x[i] == 0 ? 1 : 2);
          nodes[l].val.y[i] = nodes[a].val.y[ibuf];
        }
        for (int i = 1; i <= (int)(nodes[r].val.x.size() - 1); i++) {
          if (nodes[r].val.x[i] == -1) continue;
          int ibuf = (nodes[r].val.x[i] == 0 ? 3 : 4);
          nodes[r].val.y[i] = nodes[a].val.y[ibuf];
        }
      }
    }
    return ans;
  }
};
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  ;
  tree_t<val_t, int> T;
  cin >> T.n;
  for (int i = 0; i < (int)(T.n); i++) {
    string op;
    cin >> op;
    if (op == "NOT") {
      int s;
      cin >> s;
      s--;
      T.edges.push_back({i, s});
      array<int, 5> x = {-1, -1, -1, -1, -1};
      array<int, 5> y = {-1, -1, -1, -1, -1};
      T.vals.push_back({NOT, x, y});
    } else if (op == "IN") {
      int v;
      cin >> v;
      array<int, 5> x = {v, neg(v), -1, -1, -1};
      array<int, 5> y = {-1, -1, -1, -1, -1};
      T.vals.push_back({IN, x, y});
    } else {
      int s, t;
      cin >> s >> t;
      s--;
      t--;
      T.edges.push_back({i, s});
      T.edges.push_back({i, t});
      array<int, 5> x = {-1, -1, -1, -1, -1};
      array<int, 5> y = {-1, -1, -1, -1, -1};
      op_t opi;
      if (op == "AND") opi = AND;
      if (op == "OR") opi = OR;
      if (op == "XOR") opi = XOR;
      T.vals.push_back({opi, x, y});
    }
  }
  Tree<val_t, int> tree(T, 0);
  vector<int> ans = tree.solve();
  for (int i = 0; i < (int)(ans.size()); i++) {
    if (ans[i] != -1) cout << ans[i];
  }
  cout << endl;
}
