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