#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAX=(1<<17);
//segment tree array of size 2*max_input_array_size
int sgt[MAX*2];
//build our segment tree iteratively
void build(int n){
    //boolean to check if current operation should be OR or XOR
    bool flag=false;
    //build internal nodes i.e, other than leaf nodes
    for(int i=n-1;i>=1;i--){
        //if this node's index+1 is a power of 2 then our level is changed in tree so we have to change flag to change operation.
        if(!((i+1)&(i))){
            flag=!flag;
        }
        //if flag is true then we have to perform OR
        if(flag){
        //storing OR of child in parent
        sgt[i]=(sgt[2*i]) | (sgt[2*i+1]);
        }
        //if flag is false then we have to perform XOR
        else{
            //storing XOR of child in parent
        sgt[i]=(sgt[2*i]) ^ (sgt[2*i+1]);
        }
    }
}
//function to query the single value which is left after performing every iteration mentioned in problem
int query(int l, int r, int n)
{
    //change original index to segment tree based indexing
    l+=n;
    r+=n;
    //initialise ans to 0
    int sum=0;
    //put flag true initially to have OR operation first
    bool flag=true;
    while(l<=r)
    {
        //if left boundary is a right child(i.e, odd index) then perform operation on this node and move to right of it's parent
        if(l&1)
        {
            //if flag true then OR
            if(flag)
            sum= sum|sgt[l];
            //otherwise XOR
            else
            sum= sum^sgt[l];
            //increment left boundary
            l++;
        }
        
        //if right boundary is a left child(i.e, even index) then perform operation on this node and move to left of it's parent
        if(!(r&1))
        {
            //if flag true then OR
            if(flag)
            sum=sum|sgt[r];
            //otherwise XOR
            else
            sum= sum^sgt[l];
            //decrement right boundary
            r--;
        }
        //move up to previous level
        l=l>>1;//l=l/2;
        r=r>>1;//r=r/2;
        
        //change operation as level is changed in segment tree
        flag=!flag;
    }
    //return answer
    return sum;
}

//function to update a given element with index in in original array with value in segment tree
void update(int in, int n,int value)
{
    //change original index to segment tree based indexing
    in+=n;
    //update it's value in segment tree
    sgt[in]=value;
    
    //initially flag true i.e, operation OR to be performed
    bool flag=true;
    
    while(in>1)
    {
        //move to it's parent and update it.
        in=in>>1;//in=in/2;
        
        //if flag true then OR
        if(flag)
        sgt[in] = sgt[in*2]|sgt[in*2+1];
        
        //otherwise XOR
        else
        sgt[in] = sgt[in*2]^sgt[in*2+1];
        //change operation as level in segment tree is changed
        flag=!flag;
    }
    return;
}
//driver function
int32_t main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    //2^n is size of the array and q is number of queries
    int n,q;
    cin>>n>>q;
    //size of array
    int sz=(1<<n);
    
    int arr[sz];
    
    for(int i=0;i<sz;i++)
    {
        cin>>arr[i];
        //put array element into leaf of segment tree
        sgt[sz+i]=arr[i];
    }

    //build segment tree
    build(sz);

    //process all queries
    while(q--){
        //input index and value to be updated with
        int in,val;
        cin>>in>>val;
        //decrement index as input is 1-based and our array indexing is 0 based. 
        in--;
        //call update to update the segment tree
        update(in,sz,val);
        //print element left after all iterations as mentioned in problem
        cout<<query(0,sz-1,sz)<<"\n";
    }
    return 0;
}