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.util.*;
import java.io.*;
 
 
public class gfg  {
 
    static PrintWriter out = new PrintWriter(System.out);
    
    public static void main(String[] args) throws IOException{
        //Reader.init(System.in);
        
        Reader.init(System.in);
        int t = 1;//Reader.nextInt();
        while(t-->0){
           solve();
        }
        out.close();
    }
    
    static ArrayList<Integer>[] graph; 
    static ArrayList<Integer>[] graph2; 
    static int n=0;
    static int m=0;
    static int k =0;
    static long mod =1000000007;
    static int MOD = 1000000007;
    static int[] dx = {0,0,1,-1};
    static int[] dy = {1,-1,0,0};
    static ArrayList<Integer> list = new ArrayList<>();
    static boolean cycle= false;
    static boolean[] vis1;
    static boolean[] vis2;
    static int cnt=0;
    static int[] ans;
    static int[] dp;
 
    static trienode root = new trienode();
    static void solve()throws IOException{
        int q = Reader.nextInt();
        add(0);
        while(q-->0){
            char s = Reader.next().charAt(0);
            int x = Reader.nextInt();
            if(s=='+'){
                add(x);
            }
            if(s=='-'){
                delete(x);
            }
            if(s=='?'){
                int z = xor(x);
                out.println(z);
            }
        }
    }
    static void add(int a){
        trienode temp = root;
        for(int i=31;i>=0;i--){
            int x = a&(1<<i);
            if(x>0){
                if(temp.child[1]==null){
                    temp.child[1]= new trienode(1);
                }
                temp = temp.child[1];
                temp.p++;
            }
            else{
                if(temp.child[0]==null){
                    temp.child[0]= new trienode(0);
                }
                temp = temp.child[0];
                temp.p++;
            }
        }
        temp.cnt++;
        temp.leaf=true;
    }
    static void delete(int a){
        trienode temp = root;
        for(int i=31;i>=0;i--){
            int x = a&(1<<i);
            if(x>0){
                temp = temp.child[1];
            }
            else{
                temp = temp.child[0];
            }
            temp.p--;
            
        }
        temp.cnt--;
        if(temp.cnt==0)
            temp.leaf=false;
    }
    static int xor(int a){
        int ans=0;
        trienode temp = root;
        for(int i=31;i>=0;i--){
            int x = a&(1<<i);
            if(x>0){
                if(temp.child[0]!=null && temp.child[0].p>0){
                    temp = temp.child[0];
                    ans+=(int)Math.pow(2,i);
                }
                else if(temp.child[1]!=null && temp.child[1].p>0){
                    temp = temp.child[1];
                }
            }
            else{
                if(temp.child[1]!=null && temp.child[1].p>0){
                    temp = temp.child[1];
                    ans+=(int)Math.pow(2,i);
                }
                else if(temp.child[0]!=null && temp.child[0].p>0){
                    temp = temp.child[0];
                }
            }
        }
        return ans;
    }
    static void dfs1(int a){
        vis1[a]=true;
        for(int v : graph[a]){
            if(!vis1[v])
                dfs1(v);
        }
        list.add(a);
    }
    static void dfs2(int a){
        vis2[a] = true;
        ans[a] = cnt;
        for(int v : graph2[a]){
            if(!vis2[v])
                dfs2(v);
        }
    }
 
    
 
    
 
 
    
    
    // ggratest common divisor
    static int gcd(int a , int b){
        if(b==0)
            return a;
        else
            return gcd(b,a%b);
    }
 
    // least common multiple
    static int lcm(int a, int b){
        return (a*b)/gcd(a,b);
    }
    
    // a^b
    static long fastpow(long a, long b){
        long res = 1;a=a%mod;
        while(b>0){
            if(b%2==1)
                res = (res*a)%mod;
            a = (a*a)%mod;
            b = b>>1;
        }
        return res;
    }

    // segment tree
   /* static void update(int ind, int l, int h, int pos, int v){
        if(l==h){
            seg[ind] = v;
            return;
        }
        int mid = (l+h)/2;
        if(pos<=mid)
            update(2*ind,l,mid,pos,v);
        else
            update(2*ind+1,mid+1,h,pos,v);
        seg[ind] = seg[2*ind]^seg[2*ind+1];
    }
    static int query(int ind, int l , int h, int ll , int hh){
        if(ll>hh)
            return 0;
        if(l==ll && h==hh)
            return seg[ind];
        int mid = (l+h)/2;
        return query(2*ind,l,mid,ll,Math.min(mid,hh)) ^ query(2*ind+1,mid+1,h,Math.max(mid+1,ll),hh);
    }*/
    // priority queue with comparator
    // PriorityQueue<Interval> pq = new PriorityQueue<>(new Comparator<Interval>() {
    //             public int compare(Interval a, Interval b){
    //                 int diff1 = a.r - a.l;
    //                 int diff2 = b.r - b.l;
 
    //                 if(diff1 == diff2){
    //                     return a.l - b.l;
    //                 }
 
    //                 return diff2 - diff1;
    //             }
    // });
}
 
class trienode{
        int v;
        trienode[] child ;
        boolean leaf;
        int cnt;
        int p=0;
        trienode(int vv){
            child = new trienode[2];
            leaf=false;
            cnt=0;
            v=vv;
        }
        trienode(){
            child = new trienode[2];
            leaf=false;
            cnt=0;
            v=0;
        }
    }
class Reader {
    static BufferedReader reader;
    static StringTokenizer tokenizer;
 
    /** call this method to initialize reader for InputStream */
    static void init(InputStream input) {
        reader = new BufferedReader(
                     new InputStreamReader(input) );
        tokenizer = new StringTokenizer("");
    }
 
    /** get next word */
    static String next() throws IOException {
        while ( ! tokenizer.hasMoreTokens() ) {
            //TODO add check for eof if necessary
            tokenizer = new StringTokenizer(
                   reader.readLine() );
        }
        return tokenizer.nextToken();
    }
 
    static int nextInt() throws IOException {
        return Integer.parseInt( next() );
    }
    static long nextLong() throws IOException {
        return Long.parseLong( next() );
    }
    
    static double nextDouble() throws IOException {
        return Double.parseDouble( next() );
    }
}
class newcomparator implements Comparator<Integer>{
    //@Override
    public int compare(Integer a, Integer  b){
        return a<=b?1:-1;
    }
 }
class node {
    int f;
    int s;// cost to rreach\
    node(int ff,int ss){
        f=ff;
        s=ss;
    }
}
class mergesort{
    static void sort(int l, int h, int[] arr){
        if(l<h){
            int mid = (l+h)/2;
            
            sort(l,mid,arr);
            sort(mid+1,h,arr);
            merge(l,mid,h,arr);
        }
    }
    static void merge(int l, int m , int h , int [] arr){
 
        int[] left = new int[m-l+1];
        int[] right = new int[h-m];
        for(int i= 0 ;i< m-l+1;i++){
            left[i] = arr[l+i];
        }
        for(int i=0;i<h-m;i++){
            right[i] = arr[m+1+i];
        }
        //now left and right arrays are assumed to be sorted and we have tp merge them together 
        // int the original aaray.
        int i=l;
        int lindex = 0;
        int rindex =  0;
        
        while(lindex<m-l+1 && rindex<h-m){
            if(left[lindex]>=right[rindex]){
                arr[i]=left[lindex];
                lindex++;
                i++;
            }
            else{
                arr[i]=right[rindex];
                rindex++;
                i++;
            }
        }
        while(lindex<m-l+1){
            arr[i]=left[lindex];
            lindex++;
            i++;
        }
        while(rindex<h-m){
            arr[i]=right[rindex];
            rindex++;
            i++;
        }
    }
    
}
 
 
