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>.
/*-*-*-*-*-*| I want to see what happens if I don't give up |*-*-*-*-*-*/

import java.io.*;
import java.util.*;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.StringTokenizer;
public class Main
{
  //your static variables go here:

  static ArrayList<Integer> graph[];
  static boolean vis[];
  static int max_depth;
  static int node=-1;

  //******************************************************************
  static class FastReader
  {
      BufferedReader br;
      StringTokenizer st;
      public FastReader()
      { br = new BufferedReader(new InputStreamReader(System.in));
      }String next()
      { while (st == null || !st.hasMoreElements()){ try
      { st = new StringTokenizer(br.readLine()); }
      catch (IOException  e){e.printStackTrace();}}
      return st.nextToken();}
      int nextInt()
      {return Integer.parseInt(next());}
      long nextLong(){ return Long.parseLong(next()); }
      double nextDouble(){return Double.parseDouble(next());
      }String nextLine(){ String str = "";
      try{str = br.readLine();}
      catch (IOException e) {e.printStackTrace();}
      return str;}
    }
//*************************************************************************
/**
10
+ 8
+ 9
+ 11
+ 6
+ 1
? 3
- 8
? 3
? 8
? 11
*/

public static void main(String[] args)
{
    FastReader sc=new FastReader();
    StringBuilder sb=new StringBuilder();
    int q=sc.nextInt();
     Trie trie=new Trie();
     trie.insert(0);
    for( int i=0;i<q;i++)
    {
      char type=sc.next().charAt(0);
      int x=sc.nextInt();
      if(type=='+')
      {
        trie.insert(x);
      }
      else if(type=='-')
      {
        trie.remove(x);
      }
      else
      {
        int ans=trie.query(x);
        sb.append(ans);
        sb.append("\n");
      }
    }
    System.out.println(sb.toString());

}
public static int Diameter( int u)
{
  max_depth=-1;
    Arrays.fill(vis,false);
  dfs(u,0);
  max_depth=-1;
  Arrays.fill(vis,false);
  //System.out.println(node);
  dfs(node,0);
  return max_depth;
}
public static void dfs( int u, int depth)
{
  vis[u]=true;
  if(max_depth<depth)
  {
    max_depth=depth;
    node=u;
  }
  for( int i=0;i<graph[u].size();i++)
  {
    int v=graph[u].get(i);
    if(!vis[v])
    {
      dfs(v,depth+1);
    }
  }
}

}
class Pair
{
  int key;
  int count;
  Pair(int key, int count)
  {
    this.key=key;
    this.count=count;
  }
}

class Trie{
  static Trie root=new Trie();
  Pair value;
  boolean is_end;
  Trie child[]=new Trie[2];
  Trie()
  {
    value=new Pair(0, 0);
    child[0]=child[1]=null;
    is_end=false;
  }

  // when inserting just consider that your root is not NULL
  // you have two paths of weight 0 and 1 edge me || alphabets || ya kuch bhi
  // traverse them bit by bit starting with msb || iss ques ke basis pe
  // jab tk match hai follow that path else create a new node
  // last node me u use it to store any kind of value
  // jaise ki jo question me hoga
  // instance: yahan pe value of key
  // dictionary me word ka meaning etc...

  public static void insert( int x)
  {
    Trie temp=root;
    int cur=0;
    //in replacement to int_size check what works
    for( int i=31;i>=0;i--)
    {
      if((x&(1<<i))==(1<<i))
      cur=1;
      else
      cur=0;
      if(temp!=null&&temp.child[cur]==null)
      {
        temp.child[cur]=new Trie();
      }
      temp.child[cur].value.count++;
      temp=temp.child[cur];
    }
    temp.value.key=x;
    temp.is_end=true;
  }

  public static void remove(int x)
  {
    Trie temp=root;
    for( int i=31;i>=0;i--)
    {
      int cur=0;
      if((x&(1<<i))==(1<<i))
      {
        cur=1;
      }
      else
      cur=0;
      temp.child[cur].value.count--;
      temp=temp.child[cur];
    }

  }

  // query ke liye just think like kaise traverse krna hai and then last me jo bhi
  // value milegi how to deal with it
  // use your brain :p
  // maan lo root null nhi h

  public static int query( int x)
  {
    Trie temp=root;
    for( int i=31 ;i>=0;i--)
    {
      int cur=0;
      if(((x&(1<<i))==(1<<i)))
        cur=1;
      else
        cur=0;
      if(temp.child[1-cur]!=null&&temp.child[1-cur].value.count>0)
      {
        temp=temp.child[1-cur];
      }
      else
      {
        temp=temp.child[cur];
      }
    }
    return temp.value.key^x;
  }

}
class DSU
{
    int[] p, r;

    DSU(int N) {
        p = new int[N];
        r = new int[N];
        for(int i = 0; i < N; ++i)
            p[i] = i;
    }

    int find(int x)
    {
      return x == p[x] ? x : find(p[x]);
    }

    boolean union(int x, int y) {
        x = find(x);
        y = find(y);

        if(x == y) return false;

        if(r[x] > r[y]) {
            p[y] = x;
        } else {
            p[x] = y;
            if(r[x] == r[y])
                ++r[y];
        }
        return true;
    }
  }
