Author has gone out of the stories about Vasiliy, so here is just a formal task description.

You are given q queries and a multiset A, initially containing only integer 0. There are three types of queries:

  1. "+ x" — add integer x to multiset A.
  2. "- x" — erase one occurrence of integer x from multiset A. It's guaranteed that at least one x is present in the multiset A before this query.
  3. "? x" — you are given integer x and need to compute the value <image>, i.e. the maximum value of bitwise exclusive OR (also know as XOR) of integer x and some integer y from the multiset A.



Multiset is a set, where equal elements are allowed.

Input

The first line of the input contains a single integer q (1 ≤ q ≤ 200 000) — the number of queries Vasiliy has to perform.

Each of the following q lines of the input contains one of three characters '+', '-' or '?' and an integer xi (1 ≤ xi ≤ 109). It's guaranteed that there is at least one query of the third type.

Note, that the integer 0 will always be present in the set A.

Output

For each query of the type '?' print one integer — the maximum value of bitwise exclusive OR (XOR) of integer xi and some integer from the multiset A.

Example

Input

10
+ 8
+ 9
+ 11
+ 6
+ 1
? 3
- 8
? 3
? 8
? 11


Output

11
10
14
13

Note

After first five operations multiset A contains integers 0, 8, 9, 11, 6 and 1.

The answer for the sixth query is integer <image> — maximum among integers <image>, <image>, <image>, <image> and <image>.
import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

/**
 * Created by WiNDWAY on 8/20/16.
 */

public class Codeforces_round_367_div_2_VasiliyMultiset {

    public static void main(String[] args) {
        FScanner input = new FScanner();
        out = new PrintWriter(new BufferedOutputStream(System.out), true);
        int iteration = input.nextInt();
        BinaryTree tree = new BinaryTree();
        for (int i = 0; i < iteration; i++) {
            String[] operations = input.nextLine().split(" ");
            int value = Integer.parseInt(operations[1]);
            if (operations[0].equals("+")) {
                tree.add(value);
            } else if (operations[0].equals("?")) {
                int bestFind = tree.find(value);
                out.println((bestFind ^ value) > value ? bestFind ^ value : value);
            } else {
                tree.delete(value);
            }
        }
        out.close();
    }

    static class BinaryTree {

        Node root;

        public BinaryTree() {
            root = new Node();
            root.parent = null;
            add(0);
        }

        private class Node {
            int count;
            Node leftOne, rightZero, parent;

            public Node() {
                count = 1;
            }
        }

        public static String paddingZero(String binaryString) {
            String prepend = "";
            for (int i = 1; i <= 32 - binaryString.length(); i++) {
                prepend += "0";
            }
            return prepend + binaryString;
        }

        private int[] getBitArray(int value) {
            String binaryString = paddingZero(Integer.toBinaryString(value));
            int[] array = new int[32];
            for (int i = 0; i < binaryString.length(); i++) {
                array[i] = binaryString.charAt(i) == '0' ? 0 : 1;
            }
            return array;
        }

        public void delete(int value) {
            int[] bitArray = getBitArray(value);
            Node currentNode = root;
            boolean removal = false;
            for (int i = 0; i < bitArray.length; i++) {
                currentNode = bitArray[i] == 1 ? currentNode.leftOne : currentNode.rightZero;
                if (i == bitArray.length - 1) {
                    currentNode.count--;
                    if (currentNode.count == 0) {
                        removal = true;
                    }
                }
            }

            while (removal) {
                if (currentNode.parent.leftOne == currentNode) {
                    currentNode.parent.leftOne = null;
                } else if (currentNode.parent.rightZero == currentNode) {
                    currentNode.parent.rightZero = null;
                }
                if (currentNode.parent.leftOne != null || currentNode.parent.rightZero != null) {
                    removal = false;
                } else {
                    currentNode = currentNode.parent;
                }
            }
        }

        public int find(int value) {
            int[] bitArray = getBitArray(value);
            int[] resultArray = new int[bitArray.length];
            Node currentNode = root;
            for (int i = 0; i < bitArray.length; i++) {
                if (bitArray[i] == 1) {
                    if (currentNode.rightZero != null) {
                        currentNode = currentNode.rightZero;
                    } else if (currentNode.leftOne != null) {
                        resultArray[i] = 1;
                        currentNode = currentNode.leftOne;
                    }
                } else {
                    if (currentNode.leftOne != null) {
                        resultArray[i] = 1;
                        currentNode = currentNode.leftOne;
                    } else if (currentNode.rightZero != null) {
                        currentNode = currentNode.rightZero;
                    }
                }
            }
            int solution = 0;
            for (int i = 0; i < resultArray.length; i++) {
                solution += resultArray[i] == 1 ? 1 << (31 - i) : 0;
            }
            return solution;
        }

        public void add(int value) {
            int[] bitArray = getBitArray(value);
            Node currentNode = root;
            boolean repeatedPath = false;
            for (int i = 0; i < bitArray.length; i++) {
                if (bitArray[i] == 1) {
                    if (currentNode.leftOne != null) {
                        currentNode = currentNode.leftOne;
                    } else {
                        Node newNode = new Node();
                        newNode.parent = currentNode;
                        currentNode.leftOne = newNode;
                        currentNode = newNode;
                        repeatedPath = true;
                    }
                } else {
                    if (currentNode.rightZero != null) {
                        currentNode = currentNode.rightZero;
                    } else {
                        Node newNode = new Node();
                        newNode.parent = currentNode;
                        currentNode.rightZero = newNode;
                        currentNode = newNode;
                        repeatedPath = true;
                    }
                }
            }
            if (!repeatedPath) {
                currentNode.count++;
            }
        }
    }

    public static PrintWriter out;

    public static class FScanner {
        BufferedReader br;
        StringTokenizer st;

        public FScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        private String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

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

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

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

        public String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }
}