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;

public class Main {

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader inp = new BufferedReader (new InputStreamReader(System.in));
	    int T= Integer.parseInt(inp.readLine());
	    Trie x = new Trie();
	    char[] zero = new char[32];
	    for(int i = 0; i <  32; i++)
	    	zero [i] = '0';
	    x.insert(zero);
	    for(int i=0;i<T;i++) {
	        String s[]= inp.readLine().split(" ");
	        int n = Integer.parseInt(s[1]);
	        String a = Integer.toBinaryString(n);
	        int j = 32 - a.length();
	        while( j > 0 ) {
	        	a = "0" + a;
	        	j--;
	        }
	        char[] charList = a.toCharArray();
	        if(s[0].charAt(0) == '+') 
	        	x.insert(charList);
	        else if(s[0].charAt(0) == '-') 
	        	x.delete(charList);
	        else if(s[0].charAt(0) == '?') {
	        	String r = x.XOR(charList);
	        	System.out.println(Integer.parseInt(r, 2));
	        }
	    }
//	    x.insert(new char [] {'1', '0', '0', '0'});
//	    x.insert(new char [] {'1', '0', '0', '1'});
//	    x.insert(new char [] {'0', '1', '1', '0'});
//	    x.insert(new char [] {'1', '0', '1', '1'});
//	    x.insert(new char [] {'0', '0', '0', '1'});
//	    x.delete(new char [] {'1', '0', '0', '0'});
//	    System.out.println(x.search("1000".toCharArray()));
//	    System.out.println(x.search("1001".toCharArray()));
//	    System.out.println(x.search("0110".toCharArray()));
//	    System.out.println(x.search("0001".toCharArray()));
//	    System.out.println(x.search("1011".toCharArray()));
//	    System.out.println(x.search("1111".toCharArray()));
//	    x.print();

	}
}

class Trie {
	class Node {
		int count;
		Node left;
		Node right;
		
		Node() {
			count = 0;
		}
		
		void print() {
			String s = "" + count + " --";
			if(left!=null)
				s += "0" + ", ";
			if(right!=null)
				s += "1" ;
			System.out.println(s);
			if(left!=null) left.print();
			if(right!=null) right.print();
		}
	}
	
	Node root;
	
	Trie() {
		root = new Node();
	}
	
	void insert(char[] s) {
		int slen = s.length;
		Node cur = root;
		for (int i = 0; i < slen; i++) {
			if(s[i] == '0') {
				if (cur.left == null)
					cur.left= new Node();
				cur = cur.left;
			} else {
				if (cur.right == null)
					cur.right= new Node();
				cur = cur.right;
			}
		}
		
		++cur.count;
		
	}
	
	boolean search(char[] s) {
		int slen = s.length;
		Node cur = root;
		for (int i = 0; i < slen; i++) {
			if(s[i] == '0') {
				if (cur.left == null)
					return false;
				cur = cur.left;
			} else {
				if (cur.right == null)
					return false;
				cur = cur.right;
			}
		}
		if(cur.count > 0)
			return true;
		else
			return false;
	}
	static boolean containSplit(Node n) {
		Node cur = n;
		if(cur.left != null && cur.right != null)
			return true;
		else if(cur.left != null)
			return containSplit(cur.left);
		else if(cur.right != null)
			return containSplit(cur.right);
		else
			return false;
	}
	
	void delete(char[] s) {
		int slen = s.length;
		Node cur = root;
		for (int i = 0; i < slen; i++) {
			if(s[i] == '0') {
				if (cur.left == null)
					return ;
				cur = cur.left;
			} else {
				if (cur.right == null)
					return ;
				cur = cur.right;
			}
		}
		if(cur.count > 1){
			cur.count--;
			return;
		}
		splitDelete(s);
	}
	void splitDelete(char[] s) {
		int slen = s.length;
		Node cur = root;
		for (int i = 0; i < slen; i++) {
			if(s[i] == '0') {
				if (!containSplit(cur.left)) {
					cur.left = null;
					return ;
				}
				cur = cur.left;
			} else {
				if (!containSplit(cur.right)) {
					cur.right = null;
					return ;
				}
				cur = cur.right;
			}
		}
		cur = null;
	}
	
	void print() {
		root.print();
	}
	
	String XOR(char[]  s) {
		int slen = s.length;
		Node cur = root;
		String r = "";
		for (int i = 0; i < slen; i++) {
			if(s[i] == '0') {
				if(cur.right != null) {
					r += "1";
					cur = cur.right;
				} else {
					r += "0";
					cur = cur.left;
				}
			} else {
				if(cur.left != null) {
					r += "1";
					cur = cur.left;
				} else {
					r += "0";
					cur = cur.right;
				}
			}
		}
		return r;
	}
}