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.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;

public class Main {

    public class Trie {

        class Node {

            boolean end;
            int cnt;
            Node[] next;

            Node() {
                next = new Node[2];
            }
        }

        Node root;

        Trie() {
            root = new Node();
        }

        void insert(char... s) {
            int slen = s.length;
            Node cur = root;
            for (int i = 0; i < slen; i++) {
                int nextIdx = s[i] - '0';
                if (cur.next[nextIdx] == null) {
                    cur.next[nextIdx] = new Node();
                }
                cur = cur.next[nextIdx];
            }
            cur.cnt++;
            cur.end = true;
        }

        void delete(char... s) {
            int slen = s.length;
            Node cur = root;
            boolean kill = false;
            Deque<Node> stack = new ArrayDeque<>();
            for (int i = 0; i < slen; i++) {
                stack.push(cur);
                int nextIdx = s[i] - '0';
                if (i == slen - 1) {
                   if(--cur.next[nextIdx].cnt == 0){
                       cur.next[nextIdx] = null;
                       kill = true;
                   }      
                } else {
                    cur = cur.next[nextIdx];
                }
            }
            while (kill && !stack.isEmpty()) {
                Node node = stack.pop();
                if (node == root) {
                    break;
                }

                if (node.next[0] == null && node.next[1] == null) {
                    Node parent = stack.peek();
                    if (parent.next[0] == node) {
                        parent.next[0] = null;
                    }
                    if (parent.next[1] == node) {
                        parent.next[1] = null;
                    }
                }
            }

        }

        void print() {
            Node cur = root;
            while (true) {
                if (cur.next[0] != null) {
                    System.out.println("");
                }
            }
        }

        String solve(char... s) {
            int slen = s.length;
            Node cur = root;
            String sol = "";
            for (int i = 0; i < slen; i++) {
                int nextIdx = s[i] - '0';
                int otherIdx = 1 - nextIdx;
                if (cur.next[otherIdx] == null) {
                    sol+= nextIdx ;
                    cur = cur.next[nextIdx];
                }
                else {
                    sol += otherIdx;
                    cur = cur.next[otherIdx];
                }
            }
            return sol;
        }

        boolean search(char... s
        ) {
            int slen = s.length;
            Node cur = root;
            for (int i = 0; i < slen; i++) {
                int nextIdx = s[i] - '0';
                if (cur.next[nextIdx] == null) {
                    return false;
                }
                cur = cur.next[nextIdx];
            }
            return cur.end;
        }

    }

    public void solve() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.valueOf(br.readLine());

        Trie trie = new Trie();
        String binary = String.format("%32s", Integer.toBinaryString(0)).replace(' ', '0');
        trie.insert(binary.toCharArray());
        
        for (int i = 0; i < n; ++i) {
            String str = br.readLine();
            char op = str.charAt(0);
            int num = Integer.parseInt(str.substring(2));
            binary = String.format("%32s", Integer.toBinaryString(num)).replace(' ', '0');

            switch (op) {
                case '+':
                    trie.insert(binary.toCharArray());
                    break;
                case '-':
                    trie.delete(binary.toCharArray());
                    break;
                case '?':
                    int sol = Integer.parseInt(trie.solve(binary.toCharArray()), 2);
                    sol ^= num;
                    System.out.println(sol);
                    
                    break;
            }
        }
    }

    public static void main(String[] args) throws IOException {

        Main main = new Main();
        main.solve();
    }
}
