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

public class xor_sp implements Runnable {

	public static void main(String[] args) {
		new Thread(new xor_sp()).start();
	}

	public void run() {
		try {
			Locale.setDefault(Locale.US);
//			br = new BufferedReader(new InputStreamReader(System.in));
//			out = new PrintWriter(System.out);
			br = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			solve();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	BufferedReader br;

	PrintWriter out;

	StringTokenizer st;

	String nextToken() throws IOException {
		while (st == null || !st.hasMoreTokens()) {
			st = new StringTokenizer(br.readLine());
		}
		return st.nextToken();
	}

	int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}
	
	void myAssert(boolean e, String s) {
		if (!e) {
			throw new Error("Assertion failure " + s);
		}
	}

	private static final String FILENAME = "xor";
	
	class Trie {
		Trie[] child = new Trie[2];
		boolean rem = false;
		void add(int[] ch, int pos) {
			if (pos == ch.length) return;
			if (child[ch[pos]] == null) {
				child[ch[pos]] = new Trie();
			}
			child[ch[pos]].add(ch, pos + 1);
		}
		void remove(int[] ch, int pos) {	
			if (pos == ch.length) { rem = true; return;}
			child[ch[pos]].remove(ch, pos + 1);
			if (child[ch[pos]].rem) child[ch[pos]] = null;
			if (child[ch[pos]] == null && child[1 - ch[pos]] == null) {
				rem = true;
				return;
			}
		}
		long find(int[] ch, int pos, long mul) {
			if (pos == ch.length) {
				return 0;
			}
			if (child[1 - ch[pos]] != null) {
				long t = child[1 - ch[pos]].find(ch, pos + 1, mul / 2);
				return /*(1 - ch[pos]) */ mul + t;
			}
			long t = child[ch[pos]].find(ch, pos + 1, mul / 2);
			return /*(ch[pos]) * mul*/ + t;
		}
	}
	
	int MAX = 32;
	
	int MAXN = 100000;
	int MAXV = 1000000000;
	
	int[] toBinary(int a) {
		int[] ret = new int[MAX];
		for (int i = MAX - 1; i >= 0; i--) {
			ret[i] = a % 2;
			a /= 2;
		}
		return ret;
	}

	public void solve() throws IOException {
		int n = nextInt();
		//myAssert((1 <= n) && (n <= MAXN), "Wrong n");
		Trie root = new Trie();
		int[] chc = toBinary(0);
		root.add(chc, 0);
		HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
		for (int i = 0; i < n; ++i) {
			char c = nextToken().charAt(0);
			int x;
			if (c == '+') {
				x = nextInt();
				if (hm.containsKey(x)) {
					hm.put(x, hm.get(x) + 1);
				} else {
					//System.out.println("add " + x);
					hm.put(x, 1);
					int[] ch = toBinary(x);
					root.add(ch, 0);
				}
			} else if (c == '-') {
				x = nextInt();
				if (hm.get(x) > 1) {
					hm.put(x, hm.get(x) - 1);
				} else {
					//System.out.println("rem " + x);
					hm.remove(x);
					int[] ch = toBinary(x);
					root.remove(ch, 0);
				}
			} else {
				x = nextInt();
				//System.out.println("solve " + x);
				int[] ch = toBinary(x);
				out.println(root.find(ch, 0, 1L << (MAX - 1) ));
			}
		}
/*		int[] a = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
			myAssert((0 <= a[i]) && (a[i] <= MAXV), "Wrong a");
			int[] ch = toBinary(a[i]);
			root.add(ch, 0);
		}
		Arrays.sort(a);
		for (int i = 0; i < a.length - 1; i++) {
			assert(a[i] != a[i + 1]);
		}
		int m = nextInt();
		myAssert((1 <= m) && (m <= MAXN), "Wrong m");
		for (int i = 0; i < m; i++) {
			int b = nextInt();
			myAssert((0 <= b) && (b <= MAXV), "Wrong b");
			int[] ch = toBinary(b);
			out.println(root.find(ch, 0, 1l << (MAX - 1)));
		} */
	}
}
	