#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define fast std::ios::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL)
#define ll long long
#define test cout<<"archit\n"
#define debug(x) cout<<x<<" "
#define debug1(x) cout<<x<<"\n"
#define debug2(x,y) cout<<x<<" "<<y<<"\n"
#define pb push_back
#define pi pair<int,int>
#define fi first
#define si second
#define mod (ll)1000000007
#define mxn 1000005
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
using namespace std;
using namespace __gnu_pbds;
typedef struct trienode
{
    int val;
    vector<int>v;
    struct trienode* child[2];
}trienode;
trienode* newNode()
{
    trienode* t = new trienode;
    t->v.clear();
    t->val=0;
    t->child[0]=t->child[1]=NULL;
    return t;
}
void insert(trienode* root, int value, int index)
{
    trienode* curr = root;
    for(int i=31;i>=0;i--){
        bool bit = value&(1<<i);
        if(curr->child[bit] == NULL){
            curr->child[bit] = newNode();
        }
        curr->child[bit]->v.pb(index);
        curr = curr->child[bit];
    }
    curr->val = value;
    return;
}
bool lieBetweenRange(vector<int>v, int left, int right)
{
    if(v.size() == 0){
        return false;
    }
    if(v[0]>right || v[v.size()-1]<left){
        return false;
    }
    int l=0,r=v.size()-1;
    while(l<=r){
        int mid = l+(r-l)/2;
        if(v[mid]>=left && v[mid]<=right){
            return true;
        }
        if(v[mid]<left){
            l=mid+1;
        }
        else if(v[mid]>right){
            r=mid-1;
        }
    }
    return false;
}
int getQuery(trienode* root, int l, int r, int value)
{
    trienode* curr = root;
    for(int i=31;i>=0;i--){
        bool bit = value&(1<<i);
        if(curr->child[1-bit]!=NULL){
            vector<int>temp = curr->child[1-bit]->v;
            if(lieBetweenRange(temp, l, r) == true){
                //test;
                curr = curr->child[1-bit];
            }
        }
        else if(curr->child[bit]!=NULL){
            vector<int>temp = curr->child[bit]->v;
            if(lieBetweenRange(temp, l, r) == true){
                curr = curr->child[bit];
            }
        }
    }
    return curr->val;
}
int main()
{
    fast;
    int q; cin>>q;
    int type,l,r,val;
    trienode* root = newNode();
    int index=1;
    for(int i=1;i<=q;i++){
        cin>>type;
        if(type == 0){
            cin>>val;
            insert(root, val, index);
            index+=1;
        }
        else{
            cin>>l>>r>>val;
            debug1(getQuery(root, l, r, val));
        }
    }
    return 0;
}
