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.ArrayList;

public class Main {
	public static String to_32(int a) {
		String s = Integer.toBinaryString(a);
		for(int x = 32 - s.length(); x > 0; x--) {
			s = "0" + s;
		}
		return s;
	}
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader inp = new BufferedReader (new InputStreamReader(System.in));
	    int T= Integer.parseInt(inp.readLine());
	    Trie trie = new Trie();
	    trie.insert(to_32(0).toCharArray());
	    ArrayList<Integer> r = new ArrayList<Integer>();
	    for(int i=0;i<T;i++) {
	        String[] s= inp.readLine().split(" ");
	        char symbol = s[0].charAt(0);
	        String myNum = to_32(Integer.parseInt(s[1]));
	        if(symbol == '+') {
	        	trie.insert(myNum.toCharArray());
	        } else if(symbol == '-') {
	        	trie.delete(myNum.toCharArray());
	        } else {
	        	r.add(Integer.parseInt(trie.getMaxXor(myNum.toCharArray()), 2));
	        }
	    }
	    for(Integer i : r)
	    	System.out.println(i);
	}
}

class Trie {
	class Node {
		int end;
		Node[] next;
		
		Node() {
			next = new Node[2];
			end = 0;
		}
		
		boolean hasSplit() {
			if(next[0] == null && next[1] == null)
				return false;
			if(next[0] != null && next[1] != null)
				return true;
			boolean a = false;
			boolean b = false;
			if(next[0] != null)
				a = next[0].hasSplit();
			if(next[1] != null)
				a = next[1].hasSplit();
			return a || b;
		}
	}
	
	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.end ++;
	}
	
	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 > 0;
	}
	
	boolean normalDelete(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];
		}
		if(cur.end > 1) {
			cur.end --;
			return true;
		} else
			return false;
	}
	
	boolean delete(char ... s) {
		if(normalDelete(s)) {
			return true;
		}
		int slen = s.length;
		Node cur = root;
		for (int i = 0; i < slen; i++) {
			int nextIdx = s[i] - '0';
			if(cur.next[nextIdx].hasSplit()) {
				cur = cur.next[nextIdx];
			} else {
				cur.next[nextIdx] = null;
				return true;
			}
		}
		cur = null;
		return true;
	}
	
	String getMaxXor(char ... s) {
		int slen = s.length;
		Node cur = root;
		String result = "";
		for (int i = 0; i < slen; i++) {
			int nextIdx = s[i] - '0';
			if(cur.next[1] != null && cur.next[0] != null) {
				result += "1";
				if(nextIdx == 0)
					cur = cur.next[1];
				else
					cur = cur.next[0];
			} else if(cur.next[0] != null) {
				result += (0 ^ nextIdx );
				cur = cur.next[0];
			} else {
				result += (1 ^ nextIdx );
				cur = cur.next[1];
			}
		}
		return result;
	}
}
