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.
import java.io.*;
import java.util.*;

public class Main {

    private static final long MOD = 998244353;

    static int[] readArray(int size, InputReader in, boolean subOne) {
        int[] a = new int[size];
        for (int i = 0; i < size; i++) {
            a[i] = in.nextInt() + (subOne ? -1 : 0);
        }
        return a;
    }

    static long[] readLongArray(int size, InputReader in) {
        long[] a = new long[size];
        for (int i = 0; i < size; i++) {
            a[i] = in.nextLong();
        }
        return a;
    }

    static void sortArray(int[] a) {
        Random random = new Random();

        for (int i = 0; i < a.length; i++) {
            int randomPos = random.nextInt(a.length);
            int t = a[i];
            a[i] = a[randomPos];
            a[randomPos] = t;
        }
        Arrays.sort(a);
    }

    private static class Node {
        String op;
        int first;
        int second;
        int result;
        int parent = -1;

        public Node(String op, int first, int second) {
            this.op = op;
            this.first = first;
            this.second = second;
        }

        public Node(String op, int first) {
            this.op = op;
            this.first = first;
        }

        public Node(int result) {
            this.op = null;
            this.result = result;
        }

        public int calculate(Node[] allNodes) {
            if (op == null) {
                return result;
            }
            if (op.equals("NOT")) {
                result = 1 - allNodes[first].result;
            } else if (op.equals("AND") || op.equals("OR") || op.equals("XOR")) {
                if (op.equals("AND")) {
                    result = allNodes[first].result & allNodes[second].result;
                } else if (op.equals("OR")) {
                    result = allNodes[first].result | allNodes[second].result;
                } else {
                    result = allNodes[first].result ^ allNodes[second].result;
                }

            }
            return result;
        }
    }

    public static void main(String[] args) throws FileNotFoundException {
//        InputReader in = new InputReader(new FileInputStream("input.txt"));
//        PrintWriter out = new PrintWriter(new BufferedOutputStream(new FileOutputStream("milkvisits.out")));
//
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));

        int n = in.nextInt();
        Node[] nodes = new Node[n];
        Queue<Integer> q = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            String op = in.nextWord();
            if (op.equals("AND") || op.equals("OR") || op.equals("XOR")) {
                nodes[i] = new Node(op, in.nextInt() - 1, in.nextInt() - 1);
            } else if (op.equals("NOT")) {
                nodes[i] = new Node(op, in.nextInt() - 1);
            } else {
                nodes[i] = new Node(in.nextInt());
                q.add(i);
            }
        }

        for (int i = 0; i < n; i++) {
            if (nodes[i].op != null) {
                if (nodes[i].op.equals("NOT")) {
                    nodes[nodes[i].first].parent = i;
                } else {
                    nodes[nodes[i].first].parent = i;
                    nodes[nodes[i].second].parent = i;
                }
            }
        }

        Set<Integer>[][] res = new Set[n][];

        while (!q.isEmpty()) {
            int v = q.poll();
            solve(v, nodes, res);
            if (nodes[v].parent != -1) {
                if (nodes[nodes[v].parent].op.equals("NOT")) {
                    q.add(nodes[v].parent);
                } else if (res[nodes[nodes[v].parent].first] != null && res[nodes[nodes[v].parent].second] != null) {
                    q.add(nodes[v].parent);
                }
            }
        }

        int[] ans = new int[n];
        Arrays.fill(ans, nodes[0].result);
        for (int i = 0; i < 2; i++) {
            for (int k : res[0][i]) {
                ans[k] = i;
            }
        }
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < n; i++) {
            if (nodes[i].op == null) {
                str.append(ans[i]);
            }
        }
        out.println(str);


        out.close();
    }

    private static void solve(int v, Node[] nodes, Set<Integer>[][] allResults) {
        nodes[v].calculate(nodes);
        if (nodes[v].op == null) {
            allResults[v] = new HashSet[2];
            allResults[v][0] = new HashSet<>();
            allResults[v][1] = new HashSet<>();
            allResults[v][1 - nodes[v].result].add(v);
            return;
        }

        if (nodes[v].op.equals("NOT")) {
            Set<Integer>[] childRes = allResults[nodes[v].first];
            allResults[v] = new HashSet[2];
            allResults[v][0] = childRes[1];
            allResults[v][1] = childRes[0];
            allResults[nodes[v].first] = null;
            return;
        }

        if (nodes[v].op.equals("OR")) {
            Set<Integer>[] firstRes = allResults[nodes[v].first];
            Set<Integer>[] secondRes = allResults[nodes[v].second];
            allResults[v] = new HashSet[2];
            if (nodes[nodes[v].first].result == 1) {
                allResults[v][1] = unionSets(secondRes[0], secondRes[1]);
                allResults[v][0] = new HashSet<>();
            } else {
                allResults[v][1] = secondRes[1];
                allResults[v][0] = secondRes[0];
            }

            if (nodes[nodes[v].second].result == 1) {
                allResults[v][1] = unionSets(allResults[v][1], unionSets(firstRes[0], firstRes[1]));
            } else {
                allResults[v][1] = unionSets(allResults[v][1], firstRes[1]);
                allResults[v][0] = unionSets(allResults[v][0], firstRes[0]);
            }
        } else if (nodes[v].op.equals("AND")) {
            Set<Integer>[] firstRes = allResults[nodes[v].first];
            Set<Integer>[] secondRes = allResults[nodes[v].second];
            allResults[v] = new HashSet[2];
            if (nodes[nodes[v].first].result == 1) {
                allResults[v][1] = secondRes[1];
                allResults[v][0] = secondRes[0];
            } else {
                allResults[v][1] = new HashSet<>();
                allResults[v][0] = unionSets(secondRes[0], secondRes[1]);
            }

            if (nodes[nodes[v].second].result == 1) {
                allResults[v][1] = unionSets(allResults[v][1], firstRes[1]);
                allResults[v][0] = unionSets(allResults[v][0], firstRes[0]);
            } else {
                allResults[v][0] = unionSets(allResults[v][0], unionSets(firstRes[0], firstRes[1]));
            }
        } else {

            Set<Integer>[] firstRes = allResults[nodes[v].first];
            Set<Integer>[] secondRes = allResults[nodes[v].second];
            allResults[v] = new HashSet[2];
            if (nodes[nodes[v].first].result == 1) {
                allResults[v][1] = secondRes[0];
                allResults[v][0] = secondRes[1];
            } else {
                allResults[v][1] = secondRes[1];
                allResults[v][0] = secondRes[0];
            }

            if (nodes[nodes[v].second].result == 1) {
                allResults[v][1] = unionSets(allResults[v][1], firstRes[0]);
                allResults[v][0] = unionSets(allResults[v][0], firstRes[1]);
            } else {
                allResults[v][1] = unionSets(allResults[v][1], firstRes[1]);
                allResults[v][0] = unionSets(allResults[v][0], firstRes[0]);
            }
        }

        allResults[nodes[v].first] = null;
        allResults[nodes[v].second] = null;

    }

    private static Set<Integer> unionSets(Set<Integer> set1, Set<Integer> set2) {
        if (set1.size() >= set2.size()) {
            set1.addAll(set2);
            return set1;
        } else {
            set2.addAll(set1);
            return set2;
        }

    }

    private static void outputArray(int[] ans, PrintWriter out, boolean addOne) {
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < ans.length; i++) {
            long an = ans[i] + (addOne ? 1 : 0);
            str.append(an).append(' ');
        }
        out.println(str);
    }

    private static void outputArray(List<Integer> ans, PrintWriter out, boolean addOne) {
        StringBuilder str = new StringBuilder();
        for (int j = 0; j < ans.size(); j++) {
            long i = ans.get(j);
            long an = i + (addOne ? 1 : 0);
            str.append(an);
            if (j < ans.size() - 1) {
                str.append(' ');
            }
        }
        out.println(str);
//        out.flush();
    }

    private static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public String nextString() {
            try {
                return reader.readLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }

        public char nextChar() {
            return next().charAt(0);
        }

        public String nextWord() {
            return next();
        }

        private List<Integer>[] readTree(int n) {
            return readGraph(n, n - 1);
        }

        private List<Integer>[] readGraph(int n, int m) {
            List<Integer>[] result = new ArrayList[n];
            for (int i = 0; i < n; i++) {
                result[i] = new ArrayList<>();
            }
            for (int i = 0; i < m; i++) {
                int u = nextInt() - 1;
                int v = nextInt() - 1;
                result[u].add(v);
                result[v].add(u);
            }
            return result;
        }

        private Map<Integer, Long>[] readWeightedGraph(int n, int m) {
            Map<Integer, Long>[] result = new HashMap[n];
            for (int i = 0; i < n; i++) {
                result[i] = new HashMap<>();
            }
            for (int i = 0; i < m; i++) {
                int u = nextInt() - 1;
                int v = nextInt() - 1;
                long w = nextLong();
                result[u].put(v, Math.min(w, result[u].getOrDefault(v, Long.MAX_VALUE)));
                result[v].put(u, Math.min(w, result[v].getOrDefault(u, Long.MAX_VALUE)));
            }
            return result;
        }

    }
}