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 MainClass
{
    public static void main(String[] args)throws IOException
    {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int q = Integer.parseInt(in.readLine());
        Trie trie = new Trie();
        StringBuilder stringBuilder = new StringBuilder();
        HashMap<Long, Integer> h = new HashMap<>();
        h.put(0L, 1);
        trie.insert(0);
        while (q-- > 0)
        {
            String s1[] = in.readLine().split(" ");
            char ch = s1[0].charAt(0);
            long x = Long.parseLong(s1[1]);
            if (ch == '+')
            {
                if (!h.containsKey(x))
                {
                    h.put(x, 1);
                    trie.insert(x);
                }
                else
                    h.put(x, h.get(x) + 1);
            }
            else if (ch == '-')
            {
                h.put(x, h.get(x) - 1);
                if (h.get(x) == 0)
                {
                    trie.delete(x);
                    h.remove(x);
                }
            }
            else
            {
                long rr = ((1L << 31) - 1) ^ x;
                long ans = trie.search(rr);
                stringBuilder.append(ans).append("\n");
            }
        }
        System.out.println(stringBuilder);
    }
}
class Trie
{

    private class TrieNode
    {
        TrieNode left;
        TrieNode right;
        int leftCount = 0;
        int rightCount = 0;
        public TrieNode()
        {
            left = null;
            right = null;
        }
    }

    private final TrieNode root;
    public Trie()
    {
        root = new TrieNode();
    }

    public void insert(long x)
    {
        TrieNode current = root;
        for (int i = 30;i>=0;i--)
        {
            long mask = 1L << i;
            int bit = ((mask & x) > 0)?1:0;
            TrieNode node = null;
            if (bit == 1)
            {
                current.leftCount++;
                node = current.left;
            }
            else
            {
                current.rightCount++;
                node = current.right;
            }
            if (node == null)
            {
                node = new TrieNode();
                if (bit == 1)
                    current.left = node;
                else
                    current.right = node;
            }
            current = node;
        }
    }

    public long search(long x)
    {
        long ans = 0L;
        TrieNode current = root;
        for (int i = 30; i >=0; i--)
        {
            long mask = 1L << i;
            int bit = ((mask & x) > 0)?1:0;
            TrieNode node = null;
            if (bit == 1)
                node = current.left;
            else
                node = current.right;
            if (node == null)
            {
                if (bit == 1)
                    node = current.right;
                else
                    node = current.left;
            }
            else
                ans += mask;
            current = node;
        }
        return ans;
    }

    public void delete(long x)
    {
        delete(root, x, 30);
    }

    private void delete(TrieNode current, long x, int index)
    {
        if (index == -1)
            return;
        long mask = 1L << index;
        int bit = ((mask & x) > 0)?1:0;
        TrieNode node = null;
        if (bit == 1)
        {
            current.leftCount --;
            node = current.left;
        }
        else
        {
            current.rightCount--;
            node = current.right;
        }
        delete(node, x, index - 1);
        if (current.leftCount == 0)
            current.left = null;
        if (current.rightCount == 0)
            current.right = null;
    }
}
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 String readLine() throws IOException
    {
        byte[] buf = new byte[64]; // line length
        int cnt = 0, c;
        while ((c = read()) != -1)
        {
            if (c == '\n')
                break;
            buf[cnt++] = (byte) c;
        }
        return new String(buf, 0, cnt);
    }

    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;
    }

    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();
    }
}