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.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Stack;

// this is not good for reading double values.
public class Problem367D {
	static long m = 100000007;

	public static void main(String[] args) throws IOException {
		Reader r = new Reader();
		PrintWriter o = new PrintWriter(System.out, false);
		int q = r.nextInt();
		HashMap<Long, Integer> map = new HashMap<>();
		Trie trie = new Trie();
		trie.add(0);
		while (q-- > 0) {
			char x = r.readString().charAt(0);
			if (x == '+') {
				long a = r.nextLong();
				if (map.containsKey(a)) {
					map.put(a, map.get(a) + 1);
				} else {
					map.put(a, 1);
					trie.add(a);
				}
			} else if (x == '-') {
				long a = r.nextLong();
				if (map.containsKey(a)) {
					int fre = map.get(a);
					if (fre > 1) {
						map.put(a, fre - 1);
					} else {
						map.remove(a);
						trie.delete(a);
					}
				}
			} else {
				long a = r.nextLong();
				o.println(trie.query(a));
			}
		}
		o.close();
	}

	static class TrieNode {
		TrieNode zero;
		TrieNode one;
		long value = -1;
	}

	static class Trie {
		TrieNode root = new TrieNode();

		void add(long n) {
			TrieNode r = root;
			for (int bit = 32; bit >= 0; bit--) {
				if (((n >> bit) & 1) == 1) {
					if (r.one == null) {
						r.one = new TrieNode();
					}
					r = r.one;
				} else {
					if (r.zero == null) {
						r.zero = new TrieNode();
					}
					r = r.zero;
				}
			}
			r.value = n;
		}

		long query(long n) {
			TrieNode r = root;
			for (int bit = 32; bit >= 0; bit--) {
				if (((n >> bit) & 1) == 1) {
					if (r.zero != null) {
						r = r.zero;
					} else {
						r = r.one;
					}
				} else {
					if (r.one != null) {
						r = r.one;
					} else {
						r = r.zero;
					}
				}
			}
			// System.out.println(r.value);
			return n ^ r.value;
		}

		void delete(long n) {
			Stack<TrieNode> st = new Stack<>();
			TrieNode r = root;
			for (int i = 32; i >= 0; i--) {
				st.push(r);
				if (((n >> i) & 1) == 1) {
					r = r.one;
				} else {
					r = r.zero;
				}
			}
			while (!st.isEmpty()) {
				TrieNode node = st.pop();
				if (node.one != null && node.one.value == n) {
					node.one = null;
				}
				if (node.zero != null && node.zero.value == n) {
					node.zero = null;
				}
				if (node.one == null && node.zero == null) {
					node.value = n;
				}
				else{
					break;
				}
			}
		}
	}

	// gcd int no
	static int gcd(int n, int r) {
		return r == 0 ? n : gcd(r, n % r);
	}

	static long[][] modPow(long[][] M, long exp) {
		long[][] result = new long[][] { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } };
		long[][] pow = M;
		while (exp != 0) {
			if ((exp & 1) == 1) {
				result = multiply(result, pow);
			}
			exp >>>= 1;
			pow = multiply(pow, pow);
		}
		return result;
	}

	static long[][] multiply(long[][] A, long[][] B) {
		long[][] C = new long[4][4];
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				long value = 0;
				for (int k = 0; k < 4; k++) {
					value += A[i][k] * B[k][j];
				}
				C[i][j] = value % m;
			}
		}
		return C;
	}

	// gcd long numbers
	static long gcd(long n, long r) {
		return r == 0 ? n : gcd(r, n % r);
	}

	// input/output
	static class Reader {
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;

		public Reader() {
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public Reader(String file_name) throws IOException {
			din = new DataInputStream(new FileInputStream(file_name));
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public final String readString() throws IOException {
			int c = read();
			while (isSpaceChar(c)) {
				c = read();
			}
			StringBuilder res = new StringBuilder();
			do {
				res.append((char) c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		private boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		public int nextInt() throws IOException {
			int ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}

		public long nextLong() throws IOException {
			long ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}

		public double nextDouble() throws IOException {
			double ret = 0, div = 1;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');
			if (c == '.')
				while ((c = read()) >= '0' && c <= '9')
					ret += (c - '0') / (div *= 10);
			if (neg)
				return -ret;
			return ret;
		}

		public int[] readIntArray(int size) throws IOException {
			int[] arr = new int[size];
			for (int i = 0; i < size; i++)
				arr[i] = nextInt();
			return arr;
		}

		public long[] readLongArray(int size) throws IOException {
			long[] arr = new long[size];
			for (int i = 0; i < size; i++)
				arr[i] = nextLong();
			return arr;
		}

		private void fillBuffer() throws IOException {
			bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			if (bytesRead == -1)
				buffer[0] = -1;
		}

		private byte read() throws IOException {
			if (bufferPointer == bytesRead)
				fillBuffer();
			return buffer[bufferPointer++];
		}

		public void close() throws IOException {
			if (din == null)
				return;
			din.close();
		}
	}
}
