#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define pp pair<int, int>
#define ppp pair<int, pp>
#define fi first
#define se second
#define esp 1e-9
#define MAXE 1000000001
#define mod 1000000007
#define N 100100
typedef long long ll;
using namespace std;
int n, x, z;
vector <int> a;
vector <int> b;

int main() {
    //freopen("in.in", "r", stdin); //freopen("ou.ou", "w", stdout);
    ios::sync_with_stdio(false);
    cin>>n>>x;
    for (int i = 1; i <= n; i++) {
        cin>>z;
        a.pb(z);
    }
    for (int i = 1; i <= n; i++) {
        cin>>z;
        b.pb(z);
    }
    sort(a.begin(), a.end());
    sort(b.begin(), b.end());
    int u = -1, v = -1;
    int mat = 1000000001;
    for (int i = 0; i < n; i++) {
        int d = x - a[i];
        //cout<<"dm "<<i<<" "<<a[i]<<" "<<d<<"\n";

        int pos = lower_bound(b.begin(), b.end(), d) - b.begin();
        if (pos != n) {
            //cout<<b[pos]<<"\n";
            if (a[i] + b[pos] < mat) {
                mat = a[i] + b[pos];
                u = i;
                v = pos;
             //   cout<<"updated: "<<u<<" "<<v<<" "<<mat<<"\n";

            }
        }

    }

    a.erase(a.begin() + u);
    b.erase(b.begin() + v);

/*    for (int i = 0; i < a.size(); i++) cout<<a[i]<<" ";
    cout<<"\n";
    for (int i = 0; i < b.size(); i++) cout<<b[i]<<" ";
    cout<<"\n";
    cout<<mat<<"\n";

    int cnt = 0;
    n--;
    for (int i = 0; i < n; i++)
        if (a[i] + b[i] < mat) cnt++;

    */
    n--;
    int cnt = 0;
    int best = n - 1;
    for (int i = 0; i < n; i++) {
        while (best > 0 && a[i] + b[best] >= mat) best--;
        if (a[i] + b[best] >= mat) break;
        best--;
        cnt++;
        if (best == 0) break;
    }

    int cnt2 = 0;
    best = n - 1;
    for (int i = 0; i < n; i++) {
        while (best > 0 && b[i] + a[best] >= mat) best--;
        if (b[i] + a[best] >= mat) break;
        best--;
        cnt2++;
        if (best == 0) break;
    }

    cout<<1<<" "<<n + 1 - min(cnt, cnt2)<<"\n";

    /**/return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>

typedef long long ll;
using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;

template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>;

#define all(x) x.begin(), x.end()
#define f(i,a,b) for(int i = (a); i <= (b); i++)
#define fd(i,a,b) for(int i = (a); i >= (b); i--)
#define mp make_pair
#define faster_io() ios_base::sync_with_stdio(false)
#define pb push_back
#define pii pair<int,int>
#define SZ(x) ((int)x.size())
#define vii vector<pair<int,int>>

const int INF = 2000000005;
const ll INFLL = 1000000000000000002ll;
const ll MOD = 1000000007;

inline ll min(ll a, ll b, ll c){return min(min(a,b),c);}
inline ll min(ll a, ll b, ll c, ll d){return min(min(min(a,b),c),d);}
inline ll max(ll a, ll b, ll c){return max(max(a,b),c);}
inline ll max(ll a, ll b, ll c, ll d){return max(max(max(a,b),c),d);}

// -------------------------------------------------------------------------------------------------------------

int N, A[100005], B[100005], X;

int main()
{
    cin >> N >> X;
    f(i,1,N) scanf("%d", &A[i]);
    f(i,1,N) scanf("%d", &B[i]);
    sort(A+1,A+N+1);
    sort(B+1,B+N+1);
    int ans = 1, j = N;
    f(i,1,N)
    {
        while(j >= 1 && A[i] + B[j] >= X) j--;
        ans = max(ans, min(N-i+1,N-j));
    }
    cout << "1 " << ans;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>

typedef long long ll;
using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;

template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>;

#define all(x) x.begin(), x.end()
#define f(i,a,b) for(int i = (a); i <= (b); i++)
#define fd(i,a,b) for(int i = (a); i >= (b); i--)
#define mp make_pair
#define faster_io() ios_base::sync_with_stdio(false)
#define pb push_back
#define pii pair<int,int>
#define SZ(x) ((int)x.size())
#define vii vector<pair<int,int>>

const int INF = 2000000005;
const ll INFLL = 1000000000000000002ll;
const ll MOD = 1000000007;

inline ll min(ll a, ll b, ll c){return min(min(a,b),c);}
inline ll min(ll a, ll b, ll c, ll d){return min(min(min(a,b),c),d);}
inline ll max(ll a, ll b, ll c){return max(max(a,b),c);}
inline ll max(ll a, ll b, ll c, ll d){return max(max(max(a,b),c),d);}

// -------------------------------------------------------------------------------------------------------------

int N, A[100005], B[100005], X;
multiset<int> S;

int main()
{
    cin >> N >> X;
    f(i,1,N) scanf("%d", &A[i]);
    f(i,1,N) scanf("%d", &B[i]);
    f(i,1,N) S.insert(B[i]);
    sort(A+1,A+N+1);
    int ans = 0;
    fd(i,N,1)
    {
        auto it = S.lower_bound(X-A[i]);
        if(it == S.end()) continue;
        S.erase(it), ans++;
    }
    cout << "1 " << ans;
}


sieve=[True]*100005
prime=[]
for i in range(2,100005):
         if(sieve[i]):
                  prime.append(i)
                  for j in range(i*i,100005,i):
                           sieve[j]=False
n=int(input())
if(n<=2):
         print(1)
         print("1 "*n)
else:
         print(2)
         for i in range(2,n+2):
                  print(sieve[i]+1,end=" ")


colors=[1]*100005
for i in range(2,100005):
         for j in range(2*i,100005,i):
                  if(colors[i]==colors[j]):
                           colors[j]+=1
n=int(input())
print(max(colors[:n+2]))
for i in range(2,n+2):
         print(colors[i],end=" ")


sieve=[True]*100005
prime=[]
for i in range(2,100005):
         if(sieve[i]):
                  prime.append(i)
                  for j in range(i*i,100005,i):
                           sieve[j]=False
color=[0]*100004
for i in range(2,100004):
         for j in prime:
                  if(i*j>=100004):
                           break
                  color[j]=color[i]^1
n=int(input())
if(n<=2):
         print(1)
         print("1 "*n)
else:
         print(2)
         for i in range(2,n+2):
                  print(color[i]+1,end=" ")


def sieve(n):
    l=[1]*n
    for i in range(2,n):
        if l[i]==1:
            for j in range (i*i,n,i):
                l[j]=0
    l[1]=0
    l[0]=0
    print(2)
    for i in range(2,len(l)):
        if l[i]==1:
            print(1,end=" ")
        else:
            print(2,end=" ")
n=int(input())
if n==1:
    print(1)
    print(1)
else:
    sieve(n+2)


def sieve(n):
    l=[1]*n
    for i in range(2,n):
        if l[i]==1:
            for j in range (i*i,n,i):
                l[j]=0
    l[1]=0
    l[0]=0
    if(n==4):
        print(1)
    else:
        print(2)
    for i in range(2,len(l)):
        if l[i]==1:
            print(1,end=" ")
        else:
            print(2,end=" ")
n=int(input())
if n==1:
    print(1)
    print(1)
else:
    sieve(n+2)


def sieve(n):
    l=[1]*n
    for i in range(2,n):
        if l[i]==1:
            for j in range (i*i,n,i):
                l[j]=0
    l[1]=0
    l[0]=0
    print(2)
    for i in range(2,len(l)):
        if l[i]==1:
            print(1,end=" ")
        else:
            print(2,end=" ")
n=int(input())
sieve(n+2)


n = int(input().strip())
arr = [0]*(n+2)
for i in range(2, n+2):
	if arr[i] == 0:
		arr[i] = 1
	for j in range(i+i, n+2, i):
		if arr[j] <= arr[i]:
			arr[j] = arr[i]+1
print(max(arr))
print(*arr[2:])


def isPrime(n):
	# a prime(except 2 or 3) is of the form 6k-1 or 6k+1
	if n == 2 or n == 3:
		return True
	if n % 2 == 0 or n % 3 == 0:
		return False
	i = 5
	w = 2
	sqN = int(pow(n, .5))
	while i <= sqN:
		if n % i == 0:
			return False
		i += w
		w = 6 - w
	return True
n = int(input().strip())
arr = [1 if isPrime(i) else 2 for i in range(2, n+2)]
print(max(arr))
print(*arr)


import math

#def almostPrime(i):
#	s = i
#	count2 =0
#	for j in prime:
#		if i%j == 0:
#			count2 += 1
#			while i%j == 0:
#				i = i/j
#		if i == 1 and count2 == 2:
#			count[0] += 1
#			return
#		elif (i == 1 and count2 >3) or i == 0:
#			return

def isPrime(i):
	if sieve[i]:
		for j in range(i*i,n+2,i):
			sieve[j] = 2

n  = int(input())

sieve = [1 for i in range(n+2)]
rnge = int(math.sqrt(n))
for i in range(2,rnge+2):
	isPrime(i)
if n >= 3:
	print(2)
else:
	print(1)
for i in range(2,n+2):
	print(sieve[i], end=' ')


def primes_upto(limit):
    num_list = [1 for i in range(0, limit + 1)]
    ctr = 2
    is_prime = [True]*(limit+1)
    for n in range(2, int(limit**0.5) + 1): # stop at ``sqrt(limit)``
        if is_prime[n]:
            for i in range(n*n, limit + 1, n):
                is_prime[i] = False
                num_list[i] = ctr
            ctr += 1
    del num_list[0]
    del num_list[1]
    return num_list

def main():
    jewels = int(input())
    result = primes_upto(jewels + 1)
    print(len(set(result)))
    for i in result:
        print(i, end=' ')

if __name__ == '__main__':
    main()


def primes_upto(limit):
    num_list = [1 for i in range(0, limit + 1)]
    ctr = 2
    is_prime = [True]*(limit+1)
    for n in range(2, int(limit**0.5) + 1): # stop at ``sqrt(limit)``
        if is_prime[n]:
            for i in range(n*n, limit + 1, n):
                is_prime[i] = False
                num_list[i] = ctr
                ctr += 1
    del num_list[0]
    del num_list[1]
    return num_list

def main():
    jewels = int(input())
    result = primes_upto(jewels + 1)
    print(len(set(result)))
    for i in result:
        print(i, end=' ')

if __name__ == '__main__':
    main()


def primes_upto(limit):
    num_list = [1 for i in range(0, limit + 1)]
    ctr = 2
    is_prime = [True]*(limit+1)
    for n in range(2, int(limit**0.5) + 1): # stop at ``sqrt(limit)``
        if is_prime[n]:
            for i in range(n*n, limit + 1, n):
                is_prime[i] = False
                num_list[i] = ctr
    del num_list[0]
    del num_list[1]
    return num_list

def main():
    jewels = int(input())
    result = primes_upto(jewels + 1)
    print(len(set(result)))
    for i in result:
        print(i, end=' ')

if __name__ == '__main__':
    main()


def primes_upto(limit):
    num_list = [1 for i in range(0, limit + 1)]
    ctr = 2
    is_prime = [True]*(limit+1)
    for n in range(2, int(limit**0.5) + 1): # stop at ``sqrt(limit)``
        if is_prime[n]:
            for i in range(n*n, limit + 1, n):
                is_prime[i] = False
                num_list[i] = ctr
                ctr += 1
    del num_list[0]
    del num_list[1]
    return num_list

def main():
    jewels = int(input())
    result = primes_upto(jewels + 1)
    print(len(set(result)))
    for i in result:
        print(i, end=' ')


def primes_upto(limit):
    num_list = [1 for i in range(0, limit + 1)]
    ctr = 2
    is_prime = [True]*(limit+1)
    for n in range(2, int(limit**0.5) + 1): # stop at ``sqrt(limit)``
        if is_prime[n]:
            for i in range(n*n, limit, n):
                is_prime[i] = False
                num_list[i] = ctr
            ctr += 1
    del num_list[0]
    del num_list[1]
    return num_list

def main():
    jewels = int(input())
    result = primes_upto(jewels + 1)
    print(len(set(result)))
    for i in result:
        print(i, end=' ')

if __name__ == '__main__':
    main()


import math

n = input()
n = int(n)
if n == 1:
    print('1')
    print('1')
if n == 2:
    print('1')
    print('1 1')
if n > 2:
    print('2')
    s = '';
    for i in range(2, n + 2):
        flag = 0
        for j in range(2, math.ceil(math.sqrt(n)) + 1):
            if (j * j > i):
                break
            if (i % j == 0):
                flag = 1
        if (flag > 0):
            s += '2 ';
        else:
            s += '1 ';
    print(s);


import math

n = input()
n = int(n)
if n == 1:
    print('1')
    print('1')
if n == 2:
    print('1')
    print('1 1')
if n > 2:
    print('2')
    s = '';
    for i in range(2, n + 2):
        flag = 0
        for j in range(2, math.ceil(math.sqrt(n)) + 1):
            if (j * j > i):
                break
            if (i % j == 0):
                flag = 1
        if (flag > 0):
            print(2, end = ' ');
        else:
            print(1, end = ' ');


import math

def prost(n):
    n = int(n)
    prime = []
    s = '';
    for i in range(2, n + 2):
        flag = 0
        for j in prime:
            if (i % j == 0):
                flag = 1
        if (flag > 0):
            s += '2 ';
        else:
            prime.append(i);
            s += '1 ';
    return s
x = input()
x = int(x)
s_3 = ''
s_3 = prost(x)
if x == 1:
    print('1')
    print('1')
if x == 2:
    print('1')
    print('1 1')
if x > 2:
    print('2')
    print (s_3)


import math

def prost(n):
    n = int(n)
    s = '';
    for i in range(2, n + 2):
        flag = 0
        for j in range(2, math.ceil(math.sqrt(n)) + 1):
            if (j * j > i):
                break
            if (i % j == 0):
                flag = 1
        if (flag > 0):
            s += '2 ';
        else:
            s += '1 ';
    return s
x = input()
x = int(x)
s_3 = ''
s_3 = prost(x)
if x == 1:
    print('1')
    print('1')
if x == 2:
    print('1')
    print('1 1')
if x > 2:
    print('2')
    print (s_3)


n = int(input())

N = n+2
mark = [2]*N

for i in range(2, N):
    if mark[i] == 2:
        for j in range(i*i, N, i):
            mark[j] = 1

print(len(set(mark[2:])))
print(*mark[2:])


N = int(10e6)+2
mark = [0]*N
prime = []

for i in range(3, N+1, 2):
    if not mark[i]:
        for j in range(3*i, N+1, i+i):
            mark[j] = 1
prime.append(2)
for i in range(3, N, 2):
    if not mark[i]:
        prime.append(i)
n = int(input())
if n > 2:
    print(2)
else:
    print(1)
for i in range(2, n+2):
    if i in prime:
        print(1, end=" ")
    else:
        print(2, end=" ")
print()


n = int(input())

N = n+2
mark = [1]*N

for i in range(2, N):
    if mark[i] == 1:
        for j in range(i*i, N, i):
            mark[j] = 2

print(len(set(mark[2:])))
print(*mark[2:])


def main(n):
    MAX = int(1e5)
    is_prime = [True] * MAX
    is_prime[0] = False
    is_prime[1] = False
    for i in range(2, n + 1):
        if is_prime[i]:
            for j in range(i * i, n + 3, i):
                is_prime[j] = False
    if n < 2:
        print(1)
    else:
        print(2)

    ret = []
    for i in range(2, n + 2):
        if not is_prime[i]:
            ret.append(1)
        else:
            ret.append(2)

    print(' '.join(list(map(str,ret))))

main(int(input()))


def main(n):
    MAX = int(n * 3)
    is_prime = [True] * MAX
    is_prime[0] = False
    is_prime[1] = False
    for i in range(2, n + 1):
        if is_prime[i]:
            for j in range(i * i, n + 3, i):
                is_prime[j] = False
    if n < 2:
        print(1, 1)
        return
    else:
        print(2)

    ret = []
    for i in range(2, n + 2):
        if not is_prime[i]:
            ret.append(1)
        else:
            ret.append(2)

    print(' '.join(list(map(str,ret))))

main(int(input()))


def main(n):
    MAX = int(1e5)
    is_prime = [True] * MAX
    is_prime[0] = False
    is_prime[1] = False
    for i in range(2, n + 1):
        if is_prime[i]:
            for j in range(i * i, n + 3, i):
                is_prime[j] = False
    if n < 2:
        print(1, 1)
        return
    else:
        print(2)

    ret = []
    for i in range(2, n + 2):
        if not is_prime[i]:
            ret.append(1)
        else:
            ret.append(2)

    print(' '.join(list(map(str,ret))))

main(int(input()))


def main(n):
    MAX = int(n * 2)
    is_prime = [True] * MAX
    is_prime[0] = False
    is_prime[1] = False
    for i in range(2, n + 1):
        if is_prime[i]:
            for j in range(i * i, n + 3, i):
                is_prime[j] = False
    if n < 2:
        print(1, 1)
        return
    else:
        print(2)

    ret = []
    for i in range(2, n + 2):
        if not is_prime[i]:
            ret.append(1)
        else:
            ret.append(2)

    print(' '.join(list(map(str,ret))))

main(int(input()))


def main(n):
    MAX = int(n * 3)
    is_prime = [True] * MAX
    is_prime[0] = False
    is_prime[1] = False
    for i in range(2, n + 1):
        if is_prime[i]:
            for j in range(i * i, n + 3, i):
                is_prime[j] = False
    if n == 1:
        print("1\n1")
        return
    elif n == 2:
        print("1\n1 1")
        return
    print(2)

    ret = []
    for i in range(2, n + 2):
        if not is_prime[i]:
            ret.append(1)
        else:
            ret.append(2)

    print(' '.join(list(map(str,ret))))

main(int(input()))


import math
n=int(input())
z=[]
for i in range(2,n+2):
    c=0
    for j in range(2,int(math.pow(i,0.5))+1):
        if (i%j)==0:
            c+=1
            break
    if c==0:
        z.append("1")
    else:
        z.append("2")
if z.count("1")>0 and z.count("2")>0:
    print(2)
else:
    print(1)
print(" ".join(z))


n=int(input())
z=[]
for i in range(2,n+2):
    c=0
    for j in range(2,i//2+1):
        if (i%j)==0:
            c+=1
    if c==0:
        z.append("1")
    else:
        z.append("2")
if z.count("1")>0 and z.count("2")>0:
    print(2)
else:
    print(1)
print(" ".join(z))


n = int(input())
a = [1]*(n+2)
if n < 3:
    print(1)
    b = [1]*n
    print(*b)
else:
    for i in range(2, n+2):
        if a[i] == 2:
            continue
        else:
            for j in range(i+i, n+2, i):
                a[j] = 2
    print(2)
    print(*a[2:])


n = int(input())
a = [1]*(n+2)
for i in range(2, n+2):
    if a[i] == 2:
        continue
    else:
        for j in range(i+i, n+2, i):
            a[j] = 2
print(2)
print(*a[2:])


n = int(input())
A=[]
for i in range(2,n+2):
    if(i%2==0):
        A.append(2)
    else:
        A.append(1)
print(len(set(A)))
print(*A)


n = int(input())
A=[1]
for i in range(3,n+2):
    if(i%2==0):
        A.append(2)
    else:
        A.append(1)
print(len(set(A)))
print(*A)


n = int(input())
j=1
A=[]
for i in range(2,n+2):
    if(i%2==0):
        A.append(j)
        j+=1
    else:
        A.append(1)
print(len(set(A)))
print(*A)


n = int(input())
A=[1]*(n+2)
for i in range(2,int((n+2)**0.5)+1):
    if(A[i]==1):
        for j in range(i*i,n+2,i):
            A[j] = 2
print(len(set(A)))
print(*A[2:])


import math
n = int(input())
prime_num = [1] * (n + 2)
prime_num[1] = 0
for i in range(2, math.ceil(n ** .5) + 1):
    if prime_num[i]:
        for j in range(i ** 2, n + 2, i):
            prime_num[j] = 0;
for i in range(2, n + 2):
    if prime_num[i]:
        print(1, end=' ')
    else:
        print(2, end=' ')


import math
n = int(input())
prime_num = [1] * (n + 2)
prime_num[1] = 0
for i in range(2, math.ceil(n ** .5) + 1):
    if prime_num[i]:
        for j in range(i ** 2, n + 2, i):
            prime_num[j] = 0;
print(2)
for i in range(2, n + 2):
    if prime_num[i]:
        print(1, end=' ')
    else:
        print(2, end=' ')


import math
n = int(input())
prime_num = [1] * (n + 2)
prime_num[1] = 0
for i in range(2, math.ceil(n ** .5) + 1):
    if prime_num[i]:
        for j in range(i ** 2, n + 2, i):
            prime_num[j] = 0;
if n > 2:
    print(2)
    for i in range(2, n + 2):
        if prime_num[i]:
            print(1, end=' ')
        else:
            print(2, end=' ')
else:
    print(1)
    for i in range(n):
        print(1, end=' ')


import math
n = int(input())
prime_num = [0] * (n + 2)
if n >= 1:
    prime_num[2] = 1
if n >= 2:
    prime_num[3] = 1
if n >= 4:
    prime_num[5] = 1
for i in range(2, math.ceil(n ** .5) + 1):
    prime = True
    for j in range(2, math.ceil(i ** .5) + 1):
        if i % j == 0:
            prime = False
            break
    if prime:
        prime_num[i] = 1
print(2)
for i in range(2, n + 2):
    if prime_num[i]:
        print(1, end=' ')
    else:
        print(2, end=' ')


def main():
    n = int(input())

    if n == 1:
        print("1")
        print("1")
        return
    elif n == 2:
        print("1")
        print("1 1")
        return
    elif n == 3:
        print("2")
        print("1 1 2")
        return
    else:
        numbers = [True] * (n+3)
        for prime in range(2, n+3):
            for i in range(2 * prime, n+3, prime):
                numbers[i] = False

        print(2)
        print(" ".join([str(1) if numbers[i+2] else str(2) for i in range(n)]))

if __name__ == '__main__':
    main()


def main():
    n = int(input())

    if n == 1:
        print("1")
        print("1")
        return
    elif n == 2:
        print("1")
        print("1 1")
        return
    elif n == 3:
        print("2")
        print("1 1 2")
        return
    else:
        numbers = [True] * (n+3)
        for prime in range(2, int((n+3) ** 0.5)):
            for i in range(prime ** 2, n+3, prime):
                numbers[i] = False

        print(2)
        print(" ".join([str(1) if numbers[i+2] else str(2) for i in range(n)]))

if __name__ == '__main__':
    main()


import math as mt
import sys,string,bisect
input=sys.stdin.readline
from collections import deque
L=lambda : list(map(int,input().split()))
Ls=lambda : list(input().split())
M=lambda : map(int,input().split())
I=lambda :int(input())
n=I()
f=[0]*2+[1]*n
for i in range(2,n+2):
    k=1
    if f[i]==1:
        for j in range(i,n+2,i):
            f[j]=k
            k+=1

print(max(f))
print(*f[2::])


import math as mt
import sys,string,bisect
input=sys.stdin.readline
from collections import deque
L=lambda : list(map(int,input().split()))
Ls=lambda : list(input().split())
M=lambda : map(int,input().split())
I=lambda :int(input())
MAXN=10**5+5
spf = [0 for i in range(MAXN)]

# Calculating SPF (Smallest Prime Factor)
# for every number till MAXN.
# Time Complexity : O(nloglogn)
def sieve():
    spf[1] = 1
    for i in range(2, MAXN):

        # marking smallest prime factor
        # for every number to be itself.
        spf[i] = i

    # separately marking spf for
    # every even number as 2
    for i in range(4, MAXN, 2):
        spf[i] = 2

    for i in range(3, mt.ceil(mt.sqrt(MAXN))):

        # checking if i is prime
        if (spf[i] == i):

            # marking SPF for all numbers
            # divisible by i
            for j in range(i * i, MAXN, i):

                # marking spf[j] if it is
                # not previously marked
                if (spf[j] == j):
                    spf[j] = i
sieve()
n=I()
if(n<3):
    print(1)
else:
    print(2)
for i in range(2,n+2):
    if(spf[i]==i):
        print("1",end=" ")
    else:
        print("2",end=" ")


import math as mt
import sys,string,bisect
input=sys.stdin.readline
from collections import deque
L=lambda : list(map(int,input().split()))
Ls=lambda : list(input().split())
M=lambda : map(int,input().split())
I=lambda :int(input())
MAXN=10**5+1
spf = [0 for i in range(MAXN)]

# Calculating SPF (Smallest Prime Factor)
# for every number till MAXN.
# Time Complexity : O(nloglogn)
def sieve():
    spf[1] = 1
    for i in range(2, MAXN):

        # marking smallest prime factor
        # for every number to be itself.
        spf[i] = i

    # separately marking spf for
    # every even number as 2
    for i in range(4, MAXN, 2):
        spf[i] = 2

    for i in range(3, mt.ceil(mt.sqrt(MAXN))):

        # checking if i is prime
        if (spf[i] == i):

            # marking SPF for all numbers
            # divisible by i
            for j in range(i * i, MAXN, i):

                # marking spf[j] if it is
                # not previously marked
                if (spf[j] == j):
                    spf[j] = i
sieve()
n=I()
if(n<3):
    print(1)
else:
    print(2)
for i in range(2,n+2):
    if(spf[i]==i):
        print("1",end=" ")
    else:
        print("2",end=" ")


#776B
from math import sqrt
n = int(input())
nums = [True]*n
primes = []
for i in range(2,n+2):
    if nums[i-2]:
        for j in range(2,(n+1)//i+1):
            nums[i*j-2] = False
print(2)
for i in range(n):
    if nums[i]:
        print(1, end=" ")
    else:
        print(2, end=" ")


#776B
from math import sqrt
n = int(input())
nums = [True]*n
for i in range(2,n+2):
    if nums[i-2]:
        for j in range(2,(n+1)//i+1):
            nums[i*j-2] = False
if n > 1:
    print(2)
else:
    print(1)
for i in range(n):
    if nums[i]:
        print(1, end=" ")
    else:
        print(2, end=" ")


#776B
from math import sqrt
n = int(input())
nums = [True]*n
primes = []
for i in range(2,n+2):
    if nums[i-2]:
        for j in range(2,(n+2)//i):
            nums[i*j-2] = False
print(2)
for i in range(n):
    if nums[i]:
        print(1, end=" ")
    else:
        print(2, end=" ")


#776B
from math import sqrt
n = int(input())
nums = [1]*n
for i in range(2,n+2):
    if nums[i-2]:
        for j in range(2,(n+1)//i+1):
            nums[i*j-2] = 0
if n > sum(nums):
    print(2)
else:
    print(1)
for i in range(n):
    if nums[i]:
        print(1, end=" ")
    else:
        print(2, end=" ")


def Sieve(n):
    l=[True for i in range(n+1)]
    p=2
    while(p*p<=n):
        if(l[p]):
            for i in range(p*p,n+1,p):
                l[i]=False
        p+=1
    for i in range(n+1):
        if(l[i]):
            l[i]=1
        else:
            l[i]=2
    return l
n=int(input())
if(n==1):
    print(1)
    print(1)
elif(n==2):
    print(1)
    print(1,1)
else:
    print(2)
    print(*Sieve(n+1)[2:])


#------------------------template--------------------------#
import os
import sys
from math import *
from collections import *
from bisect import *
from io import BytesIO, IOBase
def vsInput():
    sys.stdin = open('input.txt', 'r')
    sys.stdout = open('output.txt', 'w')
BUFSIZE = 8192
class FastIO(IOBase):
    newlines = 0
    def __init__(self, file):
        self._fd = file.fileno()
        self.buffer = BytesIO()
        self.writable = "x" in file.mode or "r" not in file.mode
        self.write = self.buffer.write if self.writable else None
    def read(self):
        while True:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            if not b:
                break
            ptr = self.buffer.tell()
            self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
        self.newlines = 0
        return self.buffer.read()
    def readline(self):
        while self.newlines == 0:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            self.newlines = b.count(b"\n") + (not b)
            ptr = self.buffer.tell()
            self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
        self.newlines -= 1
        return self.buffer.readline()
    def flush(self):
        if self.writable:
            os.write(self._fd, self.buffer.getvalue())
            self.buffer.truncate(0), self.buffer.seek(0)
class IOWrapper(IOBase):
    def __init__(self, file):
        self.buffer = FastIO(file)
        self.flush = self.buffer.flush
        self.writable = self.buffer.writable
        self.write = lambda s: self.buffer.write(s.encode("ascii"))
        self.read = lambda: self.buffer.read().decode("ascii")
        self.readline = lambda: self.buffer.readline().decode("ascii")
sys.stdin, sys.stdout = IOWrapper(sys.stdin), IOWrapper(sys.stdout)
input = lambda: sys.stdin.readline().rstrip("\r\n")
def value():return tuple(map(int,input().split()))
def array():return [int(i) for i in input().split()]
def Int():return int(input())
def Str():return input()
def arrayS():return [i for i in input().split()]

#-------------------------code---------------------------#
#vsInput()

def prime(n):
    color=[1]*(n+1)
    c=1
    pr=[True]*(n+1)
    pr[0]=False
    pr[1]=False
    p=2
    while(p*p<=n):
        #print(p,color)
        if(pr[p]==True):
            color[p]=c
            ct=c
            for j in range(p*p,n+1,p):
                ct+=1
                color[j]=ct
                pr[j]=False
        p+=1
    return color[2:]
n=Int()
ans=prime(n+1)
print(max(ans))
print(*ans)


#------------------------template--------------------------#
import os
import sys
from math import *
from collections import *
from bisect import *
from io import BytesIO, IOBase
def vsInput():
    sys.stdin = open('input.txt', 'r')
    sys.stdout = open('output.txt', 'w')
BUFSIZE = 8192
class FastIO(IOBase):
    newlines = 0
    def __init__(self, file):
        self._fd = file.fileno()
        self.buffer = BytesIO()
        self.writable = "x" in file.mode or "r" not in file.mode
        self.write = self.buffer.write if self.writable else None
    def read(self):
        while True:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            if not b:
                break
            ptr = self.buffer.tell()
            self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
        self.newlines = 0
        return self.buffer.read()
    def readline(self):
        while self.newlines == 0:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            self.newlines = b.count(b"\n") + (not b)
            ptr = self.buffer.tell()
            self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
        self.newlines -= 1
        return self.buffer.readline()
    def flush(self):
        if self.writable:
            os.write(self._fd, self.buffer.getvalue())
            self.buffer.truncate(0), self.buffer.seek(0)
class IOWrapper(IOBase):
    def __init__(self, file):
        self.buffer = FastIO(file)
        self.flush = self.buffer.flush
        self.writable = self.buffer.writable
        self.write = lambda s: self.buffer.write(s.encode("ascii"))
        self.read = lambda: self.buffer.read().decode("ascii")
        self.readline = lambda: self.buffer.readline().decode("ascii")
sys.stdin, sys.stdout = IOWrapper(sys.stdin), IOWrapper(sys.stdout)
input = lambda: sys.stdin.readline().rstrip("\r\n")
def value():return tuple(map(int,input().split()))
def array():return [int(i) for i in input().split()]
def Int():return int(input())
def Str():return input()
def arrayS():return [i for i in input().split()]

#-------------------------code---------------------------#
#vsInput()

def prime(n):
    color=[1]*(n+1)
    c=1
    pr=[True]*(n+1)
    pr[0]=False
    pr[1]=False
    p=2
    while(p*p<=n):
        #print(p,color)
        if(pr[p]==True):
            color[p]=c
            ct=2
            for j in range(p*p,n+1,p):
                color[j]=ct
                pr[j]=False
        p+=1
    return color[2:]
n=Int()
ans=prime(n+1)
print(max(ans))
print(*ans)


n=int(input())
if n<=2:
    print(1)
    if n==1:
        print(1)
    else:
        print(1,1)
else:
    arr=[1]*(n+1)
    i=2
    while(i*i<=n):
        if arr[i]==1:
            j=i
            while(j<=n//i):
                arr[i*j]=2
                j+=1
        i+=1
    print(2)
    for i in arr[2:]:
        print(i,end=' ')


n=int(input())
if n<=2:
    print(1)
    if n==1:
        print(1)
    else:
        print(1,1)
else:
    arr=[1]*(n+2)
    i=2
    while(i*i<=(n+1)):
        if arr[i]==1:
            j=i
            while(j<=(n+1)//i):
                arr[i*j]=2
                j+=1
        i+=1
    print(2)
    for i in arr[2:]:
        print(i,end=' ')


def sieve(n):
	mark = [True]*(n+1)
	p = 2
	while p*p<=n:
		if mark[p]:
			for i in range(p*p,n+1,p):
				mark[i] = False
		p+=1
	for i in range(2,n+1):
		if mark[i]:
			print(1,end=" ")
		else:
			print(2,end=" ")
n = int(input())
if n==1 or n==2:
	print(1)
else:
	print(2)
sieve(n+1)


n=int(input())
li=[0]*(n+2)
li[0]=li[1]=10**6
for i in range(2,(n+1//2)+1):
    #print(i)
    if(li[i]==0):
        #print(i)
        for j in range(i*2,n+2,i):
            #print(j)
            li[j]+=1
value=n+2-li.count(0)-2
if(value>=1):
    value=2
else:
    value=1
print(value)
#counter=2
for i in range(2,n+2):
    if(li[i]==0):
        print(1,end=' ')
    else:
        print(2,end=' ')
        #counter+=1


n=int(input())
li=[0]*(n+2)
li[0]=li[1]=10**6
for i in range(2,(n+1//2)+1):
    #print(i)
    if(li[i]==0):
        #print(i)
        for j in range(i*2,n+2,i):
            #print(j)
            li[j]+=1
value=n+2-li.count(0)-2
print(value+1)
counter=2
for i in range(2,n+2):
    if(li[i]==0):
        print(1,end=' ')
    else:
        print(counter,end=' ')
        counter+=1


n = int(input())
print(2)
ans = []

def prime(q):
    j = 2
    while j * j <= q:
        if q % j == 0:
            return False
        j += 1
    return True

for i in range(2, n + 2):
    if prime(i):
        ans.append('1')
    else:
        ans.append('2')
print(' '.join(ans))


n = int(input())
if n == 1:
    print(1)
    print(1)
elif n == 2:
    print(1)
    print('1 1')
else:
    print(2)
    ans = []

    def prime(q):
        j = 2
        while j * j <= q:
            if q % j == 0:
                return False
            j += 1
        return True

    for i in range(2, n + 2):
        if prime(i):
            ans.append('1')
        else:
            ans.append('2')
    print(' '.join(ans))


n = int(input())

prime = [True for i in range(n + 2)]
prime[0] = False
prime[1] = False

for i in range(2, n + 2):
    if prime[i]:
        for j in range(i ** 2, n + 2, i):
            prime[j] = False

print(2 if n > 2 else 1)
for i in range(n):
    if prime[i + 2]:
        print(1, end = ' ')
    else:
        print(2, end = ' ')


import math
def isprime(n):
    for i in range(2,int(math.sqrt(n))+1):
        if n%i==0:
            return 0
    return 1
n=int(input())
a=[]
prime=[]
for i in range(1,n+1):
    a.append(i+1)
for i in range(0,len(a)):
    if isprime(a[i])==0:
        prime.append(2)
    else:
        prime.append(1)
if n>=3:
    print(2)
    print(*prime)
else:
    print(1)
    print(*prime)


import math
def isprime(n):
    for i in range(2,int(math.sqrt(n))+1):
        if n%i==0:
            return 0
    return 1
n=int(input())
a=[]
prime=[]
for i in range(1,n+1):
    a.append(i+1)
for i in range(0,len(a)):
    if isprime(a[i])==0:
        prime.append(2)
    else:
        prime.append(1)
print(2)
print(*prime)


def divider(n):
    i = 2
    while i**2 <= n:
        if n % i == 0:
            return False
        i += 1
    return True

n = int(input())
ans = []
for i in range(2, n+2):
    if divider(i):
        ans.append(1)
    else:
        ans.append(2)

print(len(set(ans)))
print(*ans)


n = int( input() )
if n == 1:
  print( 1 )
  print( 1 )
elif n == 2:
  print( 1 )
  print( 1, 1 )
else:
  print( 2 )
  np = [ False for i in range( n + 1 + 1 ) ]
  for i in range( 2, n + 1 + 1 ):
    if np[ i ]:
      print( 2, end = " " )
    else:
      print( 1, end = " " )
      for j in range( i + i, n + 1 + 1, i ):
        np[ j ] = True
  print()


# https://codeforces.com/problemset/problem/776/B

n = int(input()) + 1

# Sieve of Eratosthenes.
sieve = [0 for x in range(n - 1)]
for i in range(n - 1):
    if sieve[i] is 0:
        j = 2 * (i + 2)
        while (j <= n):
            sieve[j - 2] = 1
            j += 2 * (i + 2)

# Only two colors are needed since in 1D we can alternate between two.
if n > 2:
    print(2)
else:
    print(1)

for s in sieve:
    if s is 0:
        print(1, end = ' ')
    else:
        print(2, end = ' ')


# https://codeforces.com/problemset/problem/776/B

n = int(input())

# Sieve of Eratosthenes.
sieve = [0 for x in range(n + 5)]
for i in range(2, n + 2):
    if sieve[i] is 0:
        j = 2 * i
        while (j <= n + 1):
            sieve[j] = 1
            j += i

# Only two colors are needed since in 1D we can alternate between two.
if n > 2:
    print(2)
else:
    print(1)

for s in range(2, n + 2):
    if sieve[s] is 0:
        print(1, end = ' ')
    else:
        print(2, end = ' ')


#
# Yet I'm feeling like
# 	There is no better place than right by your side
# 		I had a little taste
# 			And I'll only spoil the party anyway
# 				'Cause all the girls are looking fine
# 					But you're the only one on my mind

import sys
# import re
# inf = float("inf")
# sys.setrecursionlimit(1000000)

# abc='abcdefghijklmnopqrstuvwxyz'
# abd={'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5, 'g': 6, 'h': 7, 'i': 8, 'j': 9, 'k': 10, 'l': 11, 'm': 12, 'n': 13, 'o': 14, 'p': 15, 'q': 16, 'r': 17, 's': 18, 't': 19, 'u': 20, 'v': 21, 'w': 22, 'x': 23, 'y': 24, 'z': 25}
mod,MOD=1000000007,998244353
# vow=['a','e','i','o','u']
# dx,dy=[-1,1,0,0],[0,0,1,-1]

# from collections import deque, Counter, OrderedDict,defaultdict
# from heapq import nsmallest, nlargest, heapify,heappop ,heappush, heapreplace
# from math import ceil,floor,log,sqrt,factorial,pow,pi,gcd,log10,atan,tan
# from bisect import bisect_left,bisect_right
# import numpy as np

def get_array(): return list(map(int , sys.stdin.readline().strip().split()))
def get_ints(): return map(int, sys.stdin.readline().strip().split())
def input(): return sys.stdin.readline().strip()

n=int(input())
result=[0]*(n+2)
for i in range(2,int((n+1)**0.5)+1):
    if result[i]==0:
        result[i]=1
        for j in range(i+i,n+2,i):
            result[j]=2
result=result[2:]
for i in range(len(result)):
    if result[i]==0:
        result[i]=1
print(max(result))
print(*result)


arr=[]
def SieveOfEratosthenes(n):
    prime = [True for i in range(n + 1)]
    p = 2
    while (p * p <= n):
        if (prime[p] == True):
            for i in range(p * 2, n + 1, p):
                prime[i] = False
        p += 1
    prime[0]= False
    prime[1]= False
    for p in range(n + 1):
        if prime[p]:
            arr.append(p)
SieveOfEratosthenes(10**5)
n=int(input())
print(2)
ans=[]
for i in range(2,n+2):
    if i in arr:
        ans.append(1)
    else:
        ans.append(2)
print(*ans)


arr=[]
def SieveOfEratosthenes(n):
    prime = [True for i in range(n + 1)]
    p = 2
    while (p * p <= n):
        if (prime[p] == True):
            for i in range(p * 2, n + 1, p):
                prime[i] = False
        p += 1
    prime[0]= False
    prime[1]= False
    for p in range(n + 1):
        if prime[p]:
            arr.append(p)
SieveOfEratosthenes(10**5)
n=int(input())
if n==1:
    print(1)
    print(1)
    exit()
if n==2:
    print(1)
    print(1,1)
    exit()

print(2)
ans=[]
for i in range(2,n+2):
    if i in arr:
        ans.append(1)
    else:
        ans.append(2)
print(*ans)


def isPrime(n):
    for i in range(2,int(n**0.5)+1):
        if n%i==0:
            return False
    return True
n = int(input())
x = []
for i in range(n):
    x.append(1 if isPrime(i+2) else 2)
print(len(list(set(x))))
print(*x)


def isPrime(n):
    for i in range(2,int(n**0.5)+1):
        if n%i==0:
            return False
    return True
n = int(input())
x = []
for i in range(n):
    x.append(2 if isPrime(i+2) else 1)
print(len(list(set(x))))
print(*x)


from collections import deque
def solve(x):

    if x <= 1 : return False
    if x <= 3 : return True
    if x % 2 == 0 or x % 3 == 0 : return False

    i = 5
    while i * i <= x :
        if x % i == 0 or (x % (i + 2)) == 0 :
            return False
        i += 6

    return True

n = int(input())

arr = deque()

for i in range(1 , n + 1):
    arr.append(i + 1)

cnt = 0

res = deque()
for i in range(n):
    if solve(arr[i]) == False:
        cnt += 1
        res.append(2)
    else:
        res.append(1)

r = cnt + 1
print(r)

print(*res)


from collections import deque
def solve(x):

    if x <= 1 : return False
    if x <= 3 : return True
    if x % 2 == 0 or x % 3 == 0 : return False

    i = 5
    while i * i <= x :
        if x % i == 0 or (x % (i + 2)) == 0 :
            return False
        i += 6

    return True

n = int(input())

arr = deque()

for i in range(1 , n + 1):
    arr.append(i + 1)

#print(arr)
cnt = 0

res = deque()
for i in range(n):
    if solve(arr[i]) == False:
        cnt += 1
        res.append(2)
    else:
        res.append(1)

if cnt > 0 :
    print(2)
    print(*res)

else:
    print(1)
    print(*res)


from math import *
from sys import *
input=stdin.readline
n=int(input())
l=[]
m=2
for i in range(2,n+2):
    for j in range(2,int(sqrt(i))+1):
        if(i%j==0):
            l.append(m)
            m=m+1
            break
    else:
        l.append(1)
print(len(set(l)))
print(*l)


from math import *
from sys import *
input=stdin.readline
n=int(input())
l=[]
f=0
m=2
for i in range(2,n+2):
    for j in range(2,int(sqrt(i))+1):
        if(i%j==0):
            f=1
            break
    if(f==1):
        l.append(m)
    else:
        l.append(1)
print(len(set(l)))
print(*l)


from math import *
from sys import *
input=stdin.readline
n=int(input())
l=[]
m=2
for i in range(2,n+2):
    f=0
    for j in range(2,int(sqrt(i))+1):
        if(i%j==0):
            f=1
            break
    if(f==1):
        l.append(m)
    else:
        l.append(1)
print(len(set(l)))
print(*l)


from math import sqrt
def isprime(t):
	for i in range(2,int(sqrt(t))+1):
		if t%i==0:
			return 0
	return 1
n = int(input())
s = []
cnt = 1
r = []

for i in range(2,n+2):
	if isprime(i):
		r.append(1)
	else:
		r.append(2)
print(max(r),"\n",*r)


from math import sqrt
def isprime(t):
	for i in range(2,int(sqrt(t))+1):
		if t%i==0:
			return 0
	return 1
n = int(input())
s = []
cnt = 1
r = []
for i in range(2,int(sqrt(100000)+1)):
	if isprime(i):
		s.append(i)

for i in range(2,n+2):
	for j in range(len(s)):
		if s[j]>=i:
			break
		if i%s[j]==0:
			if r[s[j]-2]==cnt:
				cnt+=1

	r.append(cnt)
print(len({i for i in r}),"\n", *r)


from math import sqrt
def isprime(t):
	for i in range(2,int(sqrt(t))+1):
		if t%i==0:
			return 0
	return 1
n = int(input())
s = []
cnt = 1
r = []
for i in range(2,int(sqrt(100000)+1)):
	if isprime(i):
		s.append(i)

for i in range(2,n+2):
	for j in range(len(s)):
		if s[j]>=i:
			break
		if i%s[j]==0:
			if r[s[j]-2]==cnt:
				cnt+=1

	r.append(cnt)
print(*r)


n=int(input())
l=[1]*(n+2)
t=1
for i in range(2,n+2):
    if l[i]==1:
        for j in range(i+i,n+2,i):
            l[j]+=1
            t=max(t,l[j])
print(t)
print(*l[2:])


n=int(input())
l=[1]*(n+2)
t=1
for i in range(2,n+2):
    if l[i]==1:
        for j in range(i+i,n+2,i):
            l[j]=2
            t=max(t,l[j])
print(t)
print(*l[2:])


def is_prime(n):
    i = 2
    while i * i <= n:
        if n % i == 0:
            return 2
        i += 1
    return 1

n = int(input())
ans = []
print(min(2, n))
for i in range(2, n + 2):
    ans.append(is_prime(i))
print(*ans)


def is_prime(n):
    i = 2
    while i * i <= n:
        if n % i == 0:
            return 2
        i += 1
    return 1

n = int(input())
ans = []
for i in range(2, n + 2):
    ans.append(is_prime(i))
print(len(set(ans)))
print(*ans)


def is_prime(n):
    i = 2
    while i * i <= n:
        if n % i == 0:
            return 1
        i += 1
    return 2

n = int(input())
ans = []
print(2)
for i in range(2, n + 2):
    ans.append(is_prime(i))
print(*ans)


def isPrime(n):
    k=0
    if(n==2):
        return True
    else:
        for i in range(2,n//2+2):
            if(n%i==0):
                k+=1
                break
        if(k==1):
            return False
        else:
            return True
n=int(input())
c=[]
for i in range(2,n+2):
    c.append(i)
l=[]
for i in range(len(c)):
    if(isPrime(c[i])==True):
        l.append(1)
    else:
        l.append(2)
print(2)
print(*l)


def isPrime(n):
    k=0
    if(n==2):
        return True
    else:
        for i in range(2,n//2+2):
            if(n%i==0):
                k+=1
                break
        if(k==1):
            return False
        else:
            return True
n=int(input())
c=[]
for i in range(2,n+2):
    c.append(i)
l=[]
for i in range(len(c)):
    if(isPrime(c[i])==True):
        l.append(1)
    else:
        l.append(2)
print(l.count(1)+l.count(2))
print(*l)


def isPrime(n):
    k=0
    if(n==2):
        return True
    else:
        for i in range(2,n//2+2):
            if(n%i==0):
                k+=1
                break
        if(k==1):
            return False
        else:
            return True
n=int(input())
c=[]
for i in range(2,n+2):
    c.append(i)
l=[]
for i in range(len(c)):
    if(isPrime(c[i])==True):
        l.append(1)
    else:
        l.append(2)
if(l.count(2)==0):
    print(1)
    print(*l)
else:
    print(2)
    print(*l)


def isPrime(n):
    """
    Assumes that n is a positive natural number
    """
    # We know 1 is not a prime number
    if n == 1:
        return False

    i = 2
    # This will loop from 2 to int(sqrt(x))
    while i*i <= n:
        # Check if i divides x without leaving a remainder
        if n % i == 0:
            # This means that n has a factor in between 2 and sqrt(n)
            # So it is not a prime number
            return False
        i += 1
    # If we did not find any factor in the above loop,
    # then n is a prime number
    return True
n=int(input())
c=[]
for i in range(2,n+2):
    c.append(i)
l=[]
for i in range(len(c)):
    if(isPrime(c[i])==True):
        l.append(1)
    else:
        l.append(2)
if(l.count(2)==0):
    print(1)
    print(*l)
else:
    print(2)
    print(*l)


n = int(input())
if n <= 2:
    print(1)
else:
    print(2)

primes = []
for i in range(2, n + 2):
    for p in primes:
        if i % p == 0:
            print(2, end=" ")
            break
    else:
        print(1, end=" ")
        primes.append(i)


def isPrime(n):
    for i in range(2,int(n**0.5)+1):
        if n%i==0:
            return False
    return True

n = int(input())
l = []
for i in range(n):
    l.append(1 if isPrime(i+2) else 2)
print(len(list(set(l))))
print(*l)


# @Author: Lakshya Singh <target_x>
# @Date:   2020-01-14T22:45:38+05:30
# @Email:  lakshay.singh1108@gmail.com
# @Filename: 776B.py
# @Last modified by:   target_x
# @Last modified time: 2020-01-14T23:25:56+05:30

#  ______                      __              _  __
# /_  __/___ __________ ____  / /_            | |/ /
#  / / / __ `/ ___/ __ `/ _ \/ __/            |   /
# / / / /_/ / /  / /_/ /  __/ /_             /   |
# /_/  \__,_/_/   \__, /\___/\__/  ______    /_/|_|
#               /____/           /_____/

from sys import stdin, stdout, exit
import math
import sys

def target_X():

    n = int(stdin.readline())
    if(n == 1):
        print(1)
        print(1)
        sys.exit()

    isPrime = ["true"] * (n + 2)
    isPrime[0] = "false"
    isPrime[1] = "false"

    i = 2
    while i * i <= n + 1:
        if isPrime[i] == "true":
            j = i * i
            while j <= n + 1:
                isPrime[j] = "false"
                j += i
        i += 1

    print(2)

    for i in range(1, n + 1):
        if isPrime[i + 1] == "true":
            print(2, end=" ")
        else:
            print(1, end=" ")

if __name__ == "__main__":
    target_X()


# @Author: Lakshya Singh <target_x>
# @Date:   2020-01-14T22:45:38+05:30
# @Email:  lakshay.singh1108@gmail.com
# @Filename: 776B.py
# @Last modified by:   target_x
# @Last modified time: 2020-01-14T23:28:31+05:30

#  ______                      __              _  __
# /_  __/___ __________ ____  / /_            | |/ /
#  / / / __ `/ ___/ __ `/ _ \/ __/            |   /
# / / / /_/ / /  / /_/ /  __/ /_             /   |
# /_/  \__,_/_/   \__, /\___/\__/  ______    /_/|_|
#               /____/           /_____/

from sys import stdin, stdout, exit
import math
import sys

def target_X():

    n = int(stdin.readline())
    if(n < 3):
        print(1)
        for x in range(n):
            print(1, end=" ")
        sys.exit()

    isPrime = ["true"] * (n + 2)
    isPrime[0] = "false"
    isPrime[1] = "false"

    i = 2
    while i * i <= n + 1:
        if isPrime[i] == "true":
            j = i * i
            while j <= n + 1:
                isPrime[j] = "false"
                j += i
        i += 1

    print(2)

    for i in range(1, n + 1):
        if isPrime[i + 1] == "true":
            print(2, end=" ")
        else:
            print(1, end=" ")

if __name__ == "__main__":
    target_X()


# @Author: Lakshya Singh <target_x>
# @Date:   2020-01-14T22:45:38+05:30
# @Email:  lakshay.singh1108@gmail.com
# @Filename: 776B.py
# @Last modified by:   target_x
# @Last modified time: 2020-01-14T23:28:31+05:30

#  ______                      __              _  __
# /_  __/___ __________ ____  / /_            | |/ /
#  / / / __ `/ ___/ __ `/ _ \/ __/            |   /
# / / / /_/ / /  / /_/ /  __/ /_             /   |
# /_/  \__,_/_/   \__, /\___/\__/  ______    /_/|_|
#               /____/           /_____/

from sys import stdin, stdout, exit
import math
import sys

def target_X():

    n = int(stdin.readline())
    if(n < 3):
        print(1)
        for x in range(n):
            print(1, end=" ")

    isPrime = ["true"] * (n + 2)
    isPrime[0] = "false"
    isPrime[1] = "false"

    i = 2
    while i * i <= n + 1:
        if isPrime[i] == "true":
            j = i * i
            while j <= n + 1:
                isPrime[j] = "false"
                j += i
        i += 1

    print(2)

    for i in range(1, n + 1):
        if isPrime[i + 1] == "true":
            print(2, end=" ")
        else:
            print(1, end=" ")

if __name__ == "__main__":
    target_X()


import math

n = input()
n = int(n)
if n == 1:
    print('1')
    print('1')
if n == 2:
    print('1')
    print('1 1')
if n > 2:
    print('2')
    s = '';
    for i in range(2, n + 2):
        flag = 0
        for j in range(2, math.ceil(math.sqrt(n)) + 1):
            if (j * j > i):
                break
            if (i % j == 0):
                flag = 1
        if (flag > 0):
            print(2, end = ' ');
        else:
            print(1, end = ' ');


from sys import stdin,stdout,maxsize;# mod = int(1e9 + 7);#import re  # can use multiple splits
tup = lambda: map(int, stdin.readline().split())
I = lambda: int(stdin.readline())
lint = lambda: [int(x) for x in stdin.readline().split()]
#S = lambda: stdin.readline().replace('\n', '').strip()
#def grid(r, c): return [lint() for i in range(r)]
#def debug(*args, c=6): print('\033[3{}m'.format(c), *args, '\033[0m', file=stderr)
stpr = lambda x  : stdout.write(f'{x}' + '\n')
star = lambda x : print(' '.join(map(str , x)))
from _collections import defaultdict

def count(n):
    for i in range(2 , int(n**0.5)+ 2):

        if n%i==0:
            return 2
    return 1
dd = defaultdict(int)
N = I()
ans =[]
for i in range(1 , N+1 ):
    ans.append(count(i))
stpr(len(set(ans)))
star(ans)


#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>

typedef long long ll;
using namespace std;
const int N = 2000005;

int n, m;
int a[N];
int rev[N], cnt;
struct tree{
    int l, r;
    ll sum;
}tr[N << 2];

void pushup(int p)
{
    tr[p].sum = tr[p << 1].sum + tr[p << 1 | 1].sum;
}

void build(int p, int l, int r)
{
    tr[p] = {l, r, 0};
    if(l == r){
        tr[p].sum = a[r];
        return ;
    }
    int mid = l + r >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    pushup(p);
}

void modify(int l, int r, int p, int x, int val, int depth)
{
    if(l == r){
        tr[p].sum = val;
        return ;
    }
    int mid = l + r >> 1;
    if(x <= mid)modify(l, mid, p << 1 + (rev[depth] == 1), x, val, depth - 1);
    else modify(mid + 1, r, p << 1 | 1 - (rev[depth] == 1), x, val, depth - 1);
    pushup(p);
}

ll query(int rl, int rr, int p, int l, int r, int depth)
{

    if(rl >= l && rr <= r)
        return tr[p].sum;
    int mid = rl +rr >> 1;
    ll ans = 0;
    if(l <= mid)ans += query(rl, mid, p << 1 + (rev[depth] == 1), l, r, depth - 1);
    if(r > mid)ans += query(mid + 1, rr, p << 1 | 1 - (rev[depth] == 1), l, r, depth - 1);
    return ans ;
}

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= (1ll << n); ++ i)
        scanf("%d", &a[i]);
    build(1, 1, 1 << n);
    while(m -- ){
        int op, x, y;
        scanf("%d%d", &op, &x);
        if(op == 1){
            scanf("%d", &y);
            modify(1, 1 << n, 1, x, y, n);
        }
        else if(op == 2)for(int i = 0; i <= x; ++ i)rev[i] ^= 1;
        else if(op == 3)rev[x + 1] ^= 1;
        else {
            scanf("%d", &y);
            printf("%lld\n", query(1, 1 << n, 1, x, y, n));
        }
    }
    return 0;
}

/*
https://www.23txt.com/files/article/html/44/44600/16829529.html
*/


#include<bits/stdc++.h>
using namespace std;

struct SegTree{
    typedef long long ll;
    struct node{
        node *l,*r;
        ll val;
        int len,swp;
        node(){
            l=r=nullptr;
            val=len=swp=0;
        }
        void pushdown(){
            if(swp&len>>1){
                node tmp=*r;
                *r=*l;
                *l=tmp;
                swp^=len>>1;
            }
            l->swp^=swp;
            r->swp^=swp;
            swp=0;
        }
        void pullup(){
            val=l->val+r->val;
        }
    };

    int sz;
    node *root;
    void build(node *id,const int &l,const int &r,const vector<int> &a){
        id->len=r-l+1;
        if(l==r){
            id->val=a[l-1];
            return;
        }
        id->l=new node;
        id->r=new node;
        build(id->l,l,l+r>>1,a);
        build(id->r,(l+r>>1)+1,r,a);
        id->pullup();
    }
    SegTree(const int &n,const vector<int> &a){
        sz=1<<n;
        root=new node;
        build(root,1,sz,a);
    }

    void upd(node *id,const int &l,const int &r,const int &pos,const int &val){
        if(pos<l||r<pos)return;
        if(pos<=l&&r<=pos){
            id->val=val;
            return;
        }
        id->pushdown();
        upd(id->l,l,l+r>>1,pos,val);
        upd(id->r,(l+r>>1)+1,r,pos,val);
        id->pullup();
    }

    void upd(const int &pos,const int &val){
        upd(root,1,sz,pos,val);
    }

    ll qry(node *id,const int &l,const int &r,const int &ql,const int &qr){
        if(qr<l||r<ql)return 0;
        if(ql<=l&&r<=qr){
            return id->val;
        }
        id->pushdown();
        return qry(id->l,l,l+r>>1,ql,qr)+qry(id->r,(l+r>>1)+1,r,ql,qr);
    }

    ll qry(const int &l,const int &r){
        return qry(root,1,sz,l,r);
    }

    void reverse(const int &k){
        root->swp^=(1<<k)-1;
    }

    void swap(const int &k){
        root->swp^=1<<k;
    }
};

int n,q;

int main(){

    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin>>n>>q;
    vector<int> a(1<<n);
    for(int i=0;i<1<<n;i++){
        cin>>a[i];
    }
    SegTree t(n,a);
    while(q--){
        int typ,x,y;
        cin>>typ>>x;
        if(typ==1){
            cin>>y;
            t.upd(x,y);
        }else
        if(typ==2){
            t.reverse(x);
        }else
        if(typ==3){
            t.swap(x);
        }else
        if(typ==4){
            cin>>y;
            cout<<t.qry(x,y)<<'\n';
        }
    }

    return 0;
}
/*
https://www.23txt.com/files/article/html/44/44600/16829529.html
*/


/*
	Powered by C++11.
	Author : Alex_Wei.
*/

#include <bits/stdc++.h>
using namespace std;

#pragma GCC optimize(3)
//#define int long long

#define uint unsigned int
#define ll long long
#define ull unsigned long long
#define pii pair <int,int>
#define pll pair <ll,ll>
#define pdd pair <double,double>
#define fi first
#define se second
#define pb emplace_back
#define all(x) x.begin(),x.end()
#define sor(x) sort(all(x))
#define rev(x) reverse(all(x))
#define mem(x,v) memset(x,v,sizeof(x))

// Templates start.

namespace IO{
	char buf[1<<23],*p1=buf,*p2=buf,obuf[1<<23],*O=obuf;
	#ifdef __WIN32
		#define gc getchar()
	#else
		#define gc (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<22,stdin),p1==p2)?EOF:*p1++)
	#endif
	#define pc(x) (*O++=x)
	#define flush() fwrite(obuf,O-obuf,1,stdout)

	inline int read(){
		int x=0,sign=0; char s=gc;
		while(!isdigit(s))sign|=s=='-',s=gc;
		while(isdigit(s))x=(x<<1)+(x<<3)+(s-'0'),s=gc;
		return sign?-x:x;
	}
	inline void print(int x){if(x>9)print(x/10); pc(x%10+'0');}
}

namespace math{
	const int mod=1e9+7;
	const int maxn=1e6+5;

	ll ksm(ll a,ll b){ll s=1,m=a; while(b){if(b&1)s=s*m%mod; m=m*m%mod,b>>=1;} return s;}
	ll inv(ll x){return ksm(x,mod-2);}

	ll fc[maxn],ifc[maxn];
	void init_m(int n){
		fc[0]=1;
		for(int i=1;i<=n;i++)fc[i]=fc[i-1]*i%mod;
		ifc[n]=inv(fc[n]);
		for(int i=n-1;i>=0;i--)ifc[i]=ifc[i+1]*(i+1)%mod;
	}
	ll C(ll n,ll m){return fc[n]*ifc[m]%mod*ifc[n-m]%mod;}
}

// Templates end. Please give me more points.

using namespace IO;
//using namespace math;

const int N=1<<18;

ll bt,q,a[N],val[N<<2],laz[19];

void build(int l,int r,int x,int dep){
	if(l==r){
		val[x]=a[l];
		return;
	} int m=l+r>>1;
	build(l,m,x<<1,dep-1);
	build(m+1,r,x<<1|1,dep-1);
	val[x]=val[x<<1]+val[x<<1|1];
}

void modify(int l,int r,int x,int pos,int v,int dep){
	if(l==r){
		val[x]=v;
		return;
	} int m=l+r>>1;
	if(pos<=m)modify(l,m,(x<<1)^laz[dep],pos,v,dep-1);
	else modify(m+1,r,(x<<1|1)^laz[dep],pos,v,dep-1);
	val[x]=val[x<<1]+val[x<<1|1];
}

ll query(int l,int r,int ql,int qr,int dep,int x){
	if(ql<=l&&r<=qr)return val[x];
	ll m=l+r>>1,ans=0;
	if(ql<=m)ans+=query(l,m,ql,qr,dep-1,(x<<1)^laz[dep]);
	if(m<qr)ans+=query(m+1,r,ql,qr,dep-1,(x<<1|1)^laz[dep]);
	return ans;
}

int main(){
	cin>>bt>>q; int n=1<<bt;
	for(int i=1;i<=n;i++)a[i]=read();
	build(1,n,1,bt-1);
	for(int i=1;i<=q;i++){
		int op=read(),x=read(),k;
		if(op==1)k=read(),modify(1,n,1,x,k,bt-1);
		if(op==2)for(int i=0;i<x;i++)laz[i]^=1;
		if(op==3)laz[x]^=1;
		if(op==4)k=read(),cout<<query(1,n,x,k,bt-1,1)<<"\n";
	}
	return 0;
}


/*
	Powered by C++11.
	Author : Alex_Wei.
*/

#include <bits/stdc++.h>
using namespace std;

//#pragma GCC optimize(3)
//#define int long long

#define uint unsigned int
#define ll long long
#define ull unsigned long long
#define pii pair <int,int>
#define pll pair <ll,ll>
#define pdd pair <double,double>
#define fi first
#define se second
#define pb emplace_back
#define all(x) x.begin(),x.end()
#define sor(x) sort(all(x))
#define rev(x) reverse(all(x))
#define mem(x,v) memset(x,v,sizeof(x))

// Templates start.

namespace IO{
	char buf[1<<23],*p1=buf,*p2=buf,obuf[1<<23],*O=obuf;
	#ifdef __WIN32
		#define gc getchar()
	#else
		#define gc (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<22,stdin),p1==p2)?EOF:*p1++)
	#endif
	#define pc(x) (*O++=x)
	#define flush() fwrite(obuf,O-obuf,1,stdout)

	inline int read(){
		int x=0,sign=0; char s=gc;
		while(!isdigit(s))sign|=s=='-',s=gc;
		while(isdigit(s))x=(x<<1)+(x<<3)+(s-'0'),s=gc;
		return sign?-x:x;
	}
	inline void print(int x){if(x>9)print(x/10); pc(x%10+'0');}
}

namespace math{
	const int mod=1e9+7;
	const int maxn=1e6+5;

	ll ksm(ll a,ll b){ll s=1,m=a; while(b){if(b&1)s=s*m%mod; m=m*m%mod,b>>=1;} return s;}
	ll inv(ll x){return ksm(x,mod-2);}

	ll fc[maxn],ifc[maxn];
	void init_m(int n){
		fc[0]=1;
		for(int i=1;i<=n;i++)fc[i]=fc[i-1]*i%mod;
		ifc[n]=inv(fc[n]);
		for(int i=n-1;i>=0;i--)ifc[i]=ifc[i+1]*(i+1)%mod;
	}
	ll C(ll n,ll m){return fc[n]*ifc[m]%mod*ifc[n-m]%mod;}
}

// Templates end. Please give me more points.

using namespace IO;
//using namespace math;

const int N=1<<18;

ll bt,q,a[N],val[N<<2],laz[19];

void build(int l,int r,int x,int dep){
	if(l==r){
		val[x]=a[l];
		return;
	} int m=l+r>>1;
	build(l,m,x<<1,dep-1);
	build(m+1,r,x<<1|1,dep-1);
	val[x]=val[x<<1]+val[x<<1|1];
}

void modify(int l,int r,int x,int pos,int v,int dep){
	if(l==r){
		val[x]=v;
		return;
	} int m=l+r>>1;
	if(pos<=m)modify(l,m,(x<<1)^laz[dep],pos,v,dep-1);
	else modify(m+1,r,(x<<1|1)^laz[dep],pos,v,dep-1);
	val[x]=val[x<<1]+val[x<<1|1];
}

ll query(int l,int r,int ql,int qr,int dep,int x){
	if(ql<=l&&r<=qr)return val[x];
	ll m=l+r>>1,ans=0;
	if(ql<=m)ans+=query(l,m,ql,qr,dep-1,(x<<1)^laz[dep]);
	if(m<qr)ans+=query(m+1,r,ql,qr,dep-1,(x<<1|1)^laz[dep]);
	return ans;
}

int main(){
	cin>>bt>>q; int n=1<<bt;
	for(int i=1;i<=n;i++)a[i]=read();
	build(1,n,1,bt-1);
	for(int i=1;i<=q;i++){
		int op=read(),x=read(),k;
		if(op==1)k=read(),modify(1,n,1,x,k,bt-1);
		if(op==2)for(int i=0;i<x;i++)laz[i]^=1;
		if(op==3)laz[x]^=1;
		if(op==4)k=read(),cout<<query(1,n,x,k,bt-1,1)<<"\n";
	}
	return 0;
}


/*
	Powered by C++11.
	Author : Alex_Wei.
*/

#include <bits/stdc++.h>
using namespace std;

#pragma GCC optimize(3)
//#define int long long

#define uint unsigned int
#define ll long long
#define ull unsigned long long
#define pii pair <int,int>
#define pll pair <ll,ll>
#define pdd pair <double,double>
#define fi first
#define se second
#define pb emplace_back
#define all(x) x.begin(),x.end()
#define sor(x) sort(all(x))
#define rev(x) reverse(all(x))
#define mem(x,v) memset(x,v,sizeof(x))

// Templates start.

namespace IO{
	char buf[1<<23],*p1=buf,*p2=buf,obuf[1<<23],*O=obuf;
	#ifdef __WIN32
		#define gc getchar()
	#else
		#define gc (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<22,stdin),p1==p2)?EOF:*p1++)
	#endif
	#define pc(x) (*O++=x)
	#define flush() fwrite(obuf,O-obuf,1,stdout)

	inline int read(){
		int x=0,sign=0; char s=gc;
		while(!isdigit(s))sign|=s=='-',s=gc;
		while(isdigit(s))x=(x<<1)+(x<<3)+(s-'0'),s=gc;
		return sign?-x:x;
	}
	inline void print(int x){if(x>9)print(x/10); pc(x%10+'0');}
}

namespace math{
	const int mod=1e9+7;
	const int maxn=1e6+5;

	ll ksm(ll a,ll b){ll s=1,m=a; while(b){if(b&1)s=s*m%mod; m=m*m%mod,b>>=1;} return s;}
	ll inv(ll x){return ksm(x,mod-2);}

	ll fc[maxn],ifc[maxn];
	void init_m(int n){
		fc[0]=1;
		for(int i=1;i<=n;i++)fc[i]=fc[i-1]*i%mod;
		ifc[n]=inv(fc[n]);
		for(int i=n-1;i>=0;i--)ifc[i]=ifc[i+1]*(i+1)%mod;
	}
	ll C(ll n,ll m){return fc[n]*ifc[m]%mod*ifc[n-m]%mod;}
}

// Templates end. Please give me more points.

using namespace IO;
//using namespace math;

const int N=1<<19;

ll bt,q,a[N],val[N<<2],laz[19];

void build(int l,int r,int x,int dep){
	if(l==r){
		val[x]=a[l];
		return;
	} int m=l+r>>1;
	build(l,m,x<<1,dep-1);
	build(m+1,r,x<<1|1,dep-1);
	val[x]=val[x<<1]+val[x<<1|1];
}

void modify(int l,int r,int x,int pos,int v,int dep){
	if(l==r){
		val[x]=v;
		return;
	} int m=l+r>>1;
	if(pos<=m)modify(l,m,(x<<1)^laz[dep],pos,v,dep-1);
	else modify(m+1,r,(x<<1|1)^laz[dep],pos,v,dep-1);
	val[x]=val[x<<1]+val[x<<1|1];
}

ll query(int l,int r,int ql,int qr,int dep,int x){
	if(ql<=l&&r<=qr)return val[x];
	ll m=l+r>>1,ans=0;
	if(ql<=m)ans+=query(l,m,ql,qr,dep-1,(x<<1)^laz[dep]);
	if(m<qr)ans+=query(m+1,r,ql,qr,dep-1,(x<<1|1)^laz[dep]);
	return ans;
}

int main(){
	cin>>bt>>q; int n=1<<bt;
	for(int i=1;i<=n;i++)a[i]=read();
	build(1,n,1,bt-1);
	for(int i=1;i<=q;i++){
		int op=read(),x=read(),k;
		if(op==1)k=read(),modify(1,n,1,x,k,bt-1);
		if(op==2)for(int i=0;i<x;i++)laz[i]^=1;
		if(op==3)laz[x]^=1;
		if(op==4)k=read(),cout<<query(1,n,x,k,bt-1,1)<<"\n";
	}
	return 0;
}


/*
	Powered by C++11.
	Author : Alex_Wei.
*/

#include <bits/stdc++.h>
using namespace std;

//#pragma GCC optimize(3)
//#define int long long

#define uint unsigned int
#define ll long long
#define ull unsigned long long
#define pii pair <int,int>
#define pll pair <ll,ll>
#define pdd pair <double,double>
#define fi first
#define se second
#define pb emplace_back
#define all(x) x.begin(),x.end()
#define sor(x) sort(all(x))
#define rev(x) reverse(all(x))
#define mem(x,v) memset(x,v,sizeof(x))

// Templates start.

namespace IO{
	char buf[1<<23],*p1=buf,*p2=buf,obuf[1<<23],*O=obuf;
	#ifdef __WIN32
		#define gc getchar()
	#else
		#define gc (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<22,stdin),p1==p2)?EOF:*p1++)
	#endif
	#define pc(x) (*O++=x)
	#define flush() fwrite(obuf,O-obuf,1,stdout)

	inline int read(){
		int x=0,sign=0; char s=gc;
		while(!isdigit(s))sign|=s=='-',s=gc;
		while(isdigit(s))x=(x<<1)+(x<<3)+(s-'0'),s=gc;
		return sign?-x:x;
	}
	inline void print(int x){if(x>9)print(x/10); pc(x%10+'0');}
}

namespace math{
	const int mod=1e9+7;
	const int maxn=1e6+5;

	ll ksm(ll a,ll b){ll s=1,m=a; while(b){if(b&1)s=s*m%mod; m=m*m%mod,b>>=1;} return s;}
	ll inv(ll x){return ksm(x,mod-2);}

	ll fc[maxn],ifc[maxn];
	void init_m(int n){
		fc[0]=1;
		for(int i=1;i<=n;i++)fc[i]=fc[i-1]*i%mod;
		ifc[n]=inv(fc[n]);
		for(int i=n-1;i>=0;i--)ifc[i]=ifc[i+1]*(i+1)%mod;
	}
	ll C(ll n,ll m){return fc[n]*ifc[m]%mod*ifc[n-m]%mod;}
}

// Templates end. Please give me more points.

using namespace IO;
//using namespace math;

const int N=1<<18;

ll bt,q,a[N],val[N<<2],laz[18];

void build(int l,int r,int x,int dep){
	if(l==r){
		val[x]=a[l];
		return;
	} int m=l+r>>1;
	build(l,m,x<<1,dep-1);
	build(m+1,r,x<<1|1,dep-1);
	val[x]=val[x<<1]+val[x<<1|1];
}

void modify(int l,int r,int x,int pos,int v,int dep){
	if(l==r){
		val[x]=v;
		return;
	} int m=l+r>>1;
	if(pos<=m)modify(l,m,(x<<1)^laz[dep],pos,v,dep-1);
	else modify(m+1,r,(x<<1|1)^laz[dep],pos,v,dep-1);
	val[x]=val[x<<1]+val[x<<1|1];
}

ll query(int l,int r,int ql,int qr,int dep,int x){
	if(ql<=l&&r<=qr)return val[x];
	ll m=l+r>>1,ans=0;
	if(ql<=m)ans+=query(l,m,ql,qr,dep-1,(x<<1)^laz[dep]);
	if(m<qr)ans+=query(m+1,r,ql,qr,dep-1,(x<<1|1)^laz[dep]);
	return ans;
}

int main(){
	cin>>bt>>q; int n=1<<bt;
	for(int i=1;i<=n;i++)cin>>a[i];
	build(1,n,1,bt-1);
	for(int i=1;i<=q;i++){
		int op,x,k; cin>>op>>x;
		if(op==1)cin>>k,modify(1,n,1,x,k,bt-1);
		if(op==2)for(int i=0;i<x;i++)laz[i]^=1;
		if(op==3)laz[x]^=1;
		if(op==4)cin>>k,cout<<query(1,n,x,k,bt-1,1)<<endl;
	}
	return 0;
}


#include<map>
#include<list>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define in inline
#define ll long long
#define INF 2147483647
#define ri register int
#define rc register char
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
in int read(){
	rc c=' ';
	ri v=0,x=1;
	while((c<'0')||(c>'9')){if(c=='-') x=-1;c=getchar();}
	while((c>='0')&&(c<='9')){v=(v<<1)+(v<<3)+(c^48);c=getchar();}
	return v*x;
}
in void write(ll x){
	if(x<0) x=-x,putchar('-');
	if(x>9) write(x/10);
	putchar(x%10^48);
}
const int N=1<<20|15;
int n,m;
ll val[N];
bool rev[N];
void build(ri l,ri r,ri rt){
	if(l==r){
		val[rt]=read();
		return;
	}
	ri mid=l+r>>1;
	build(l,mid,ls),build(mid+1,r,rs);
	val[rt]=val[ls]+val[rs];
}
void modify(ri l,ri r,ri rt,ri dep,ri p,ri v){
	if(l==r){
		val[rt]=v;
		return;
	}
	ri mid=l+r>>1;
	if(p<=mid) modify(l,mid,ls|rev[dep],dep-1,p,v);
	else modify(mid+1,r,ls|rev[dep]^1,dep-1,p,v);
	val[rt]=val[ls]+val[rs];
}
ll query(ri l,ri r,ri rt,ri dep,ri L,ri R){
	if(L<=l&&r<=R) return val[rt];
	ri mid=l+r>>1;
	ll res=0;
	if(L<=mid) res+=query(l,mid,ls|rev[dep],dep-1,L,R);
	if(R>mid) res+=query(mid+1,r,ls|rev[dep]^1,dep-1,L,R);
	return res;
}
in void reverse(ri k){
	for(ri i=0;i<=k;i++)
		rev[i]^=1;
}
int main(){
	n=read(),m=read();
	build(1,1<<n,1);
	for(ri i=1;i<=m;i++){
		ri op=read();
		if(op==1){
			ri x=read(),y=read();
			modify(1,1<<n,1,n,x,y);
		}
		if(op==2) reverse(read());
		if(op==3) rev[read()+1]^=1;
		if(op==4){
			ri x=read(),y=read();
			write(query(1,1<<n,1,n,x,y)),putchar('\n');
		}
	}
	return ~~(0-0);
}


#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++i)
#define per(i, a, b) for (int i = (a), i##end = (b); i >= i##end; --i)

mt19937 Rnd(chrono::high_resolution_clock::now().time_since_epoch().count());

template <typename T>
inline void chkmax(T &x, T y) { if (x < y) x = y; }

template <typename T>
inline void chkmin(T &x, T y) { if (x > y) x = y; }

inline int read() {
  #define nc getchar()
  int x = 0;
  char c = nc;
  while (c < 48) c = nc;
  while (c > 47) x = x * 10 + (c ^ 48), c = nc;
  return x;
  #undef nc
}

typedef long long ll;
typedef pair <int, int> pii;
const int maxn = 1 << 18 | 5;
int n, q;

#define mid ((l + r) >> 1)
#define lson k << 1, l, mid
#define rson k << 1 | 1, mid + 1, r

bool swp[19];
bool rev[19];
ll sum[maxn << 2];

void build(int k, int l, int r) {
  if (l == r) return scanf("%lld", sum + k), void();
  build(lson), build(rson), sum[k] = sum[k << 1] + sum[k << 1 | 1];
}

void upd(int k, int l, int r, int x, int v, int dep, int flg) {
  if (l == r) return sum[k] = v, void();
  int ls = k << 1, rs = k << 1 | 1;
  if (flg) swap(ls, rs);
  if (rev[dep]) swap(ls, rs);
  if (swp[dep]) swap(ls, rs);
  flg ^= rev[dep];
  x <= mid ? upd(ls, l, mid, x, v, dep + 1, flg) : upd(rs, mid + 1, r, x, v, dep + 1, flg);
  sum[k] = sum[ls] + sum[rs];
}

ll query(int k, int l, int r, int ql, int qr, int dep, int flg) {
  if (ql <= l && r <= qr) return sum[k];
  ll res = 0;
  int ls = k << 1, rs = k << 1 | 1;
  if (flg) swap(ls, rs);
  if (rev[dep]) swap(ls, rs);
  if (swp[dep]) swap(ls, rs);
  flg ^= rev[dep];
  if (ql <= mid) res = query(ls, l, mid, ql, qr, dep + 1, flg);
  if (qr > mid) res += query(rs, mid + 1, r, ql, qr, dep + 1, flg);
  return res;
}

#undef mid
#undef lson
#undef rson

void solve() {
  cin >> n >> q;
  build(1, 1, 1 << n);
  while (q--) {
    int op = read();
    if (op == 1) {
      int x = read(), k = read();
      upd(1, 1, 1 << n, x, k, 0, 0);
    } else if (op == 2) {
      int k = read();
      rev[n - k] ^= 1;
    } else if (op == 3) {
      int k = read();
      swp[n - k - 1] ^= 1;
    } else {
      int l = read(), r = read();
      printf("%lld\n", query(1, 1, 1 << n, l, r, 0, 0));
    }
  }
}

signed main() {
//  int T = read();
//  while (T--) solve();
  solve();
  return 0;
}


#include <bits/stdc++.h>

#define R register
#define ll long long

const ll MaxN = 3e5 + 10;

ll n, q, x, a[MaxN], c[MaxN];

ll lowbit(ll x) {return x & -x;}

void add(ll pos, ll val)
{
    while(pos <= (1 << n))
        c[pos] += val, pos += lowbit(pos);
}

ll sum(ll pos)
{
    ll res = 0;
    while(pos)
        res += c[pos], pos -= lowbit(pos);
    return res;
}

ll query(ll l, ll r, ll ql, ll qr)
{
    if(l > qr || ql > r) return 0;
    // prllf("[%d %d]\n", l, r);
    if (ql <= l && r <= qr)
    {
        ll pow = r - l + 1;
        ll l1 = (l ^ x) - (l ^ x) % pow;
        return sum(l1 + pow) - sum(l1);
    }
    ll mid = (l + r) >> 1;
    return query(l, mid, ql, qr) + query(mid + 1, r, ql, qr);
}

inline ll read()
{
    ll x = 0;
    char ch = getchar();
    while(ch > '9' || ch < '0')
        ch = getchar();
    while(ch <= '9' && ch >= '0')
        x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
    return x;
}

signed main()
{
    n = read(), q = read();
    for(ll i = 0; i < (1 << n); i++)
        a[i] = read(), add(i + 1, a[i]);
    while(q--)
    {
        ll op = read();
        if(op == 1)
        {
            ll i = read() - 1, k = read();
            add((i ^ x) + 1, -a[i ^ x]), a[i ^ x] = k, add((i ^ x) + 1, k);
        }
        else if(op == 2)
        {
            ll k = read();
            x ^= ((1 << k) - 1);
        }
        else if(op == 3)
        {
            ll k = read();
            x ^= (1 << k);
        }
        else if(op == 4)
        {
            ll l = read() - 1, r = read() - 1;
            printf("%lld\n", query(0, (1 << n) - 1, l, r));
        }
    }
    return 0;
}


#include <bits/stdc++.h>

#define R register
#define ll long long

const int MaxN = 3e5 + 10;

int n, q, x, a[MaxN], c[MaxN];

int lowbit(int x) {return x & -x;}

void add(int pos, int val)
{
    while(pos <= (1 << n))
        c[pos] += val, pos += lowbit(pos);
}

int sum(int pos)
{
    int res = 0;
    while(pos)
        res += c[pos], pos -= lowbit(pos);
    return res;
}

int query(int l, int r, int ql, int qr)
{
    if(l > qr || ql > r) return 0;
    // printf("[%d %d]\n", l, r);
    if (ql <= l && r <= qr)
    {
        int pow = r - l + 1;
        int l1 = (l ^ x) - (l ^ x) % pow;
        return sum(l1 + pow) - sum(l1);
    }
    int mid = (l + r) >> 1;
    return query(l, mid, ql, qr) + query(mid + 1, r, ql, qr);
}

inline int read()
{
    int x = 0;
    char ch = getchar();
    while(ch > '9' || ch < '0')
        ch = getchar();
    while(ch <= '9' && ch >= '0')
        x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
    return x;
}

int main()
{
    n = read(), q = read();
    for(int i = 0; i < (1 << n); i++)
        a[i] = read(), add(i + 1, a[i]);
    while(q--)
    {
        int op = read();
        if(op == 1)
        {
            int i = read() - 1, k = read();
            add((i ^ x) + 1, -a[i ^ x]), a[i ^ x] = k, add((i ^ x) + 1, k);
        }
        else if(op == 2)
        {
            int k = read();
            x ^= ((1 << k) - 1);
        }
        else if(op == 3)
        {
            int k = read();
            x ^= (1 << k);
        }
        else if(op == 4)
        {
            int l = read() - 1, r = read() - 1;
            printf("%d\n", query(0, (1 << n) - 1, l, r));
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long int

int n,q,lg;
int a[262145],pow2[20];
bool rev[20];
struct BIT{
	int tree[262145];
	inline int lb(int x){return x&(-x);}
	inline void add(int x,int y)
	{
		while(x<=n){
			tree[x]+=y;
			x+=lb(x);
		}
		return;
	}
	inline int qry(int r)
	{
		int res=0;
		while(r>0){
			res+=tree[r];
			r-=lb(r);
		}
		return res;
	}
	inline int query(int l,int r)
	{
		return qry(r)-qry(l-1);
	}
}bit;

void change(int pos,int k,int x)
{
	if(x==0){
		bit.add(pos,k-a[pos]);
		a[pos]=k;
		return;
	}
	int t=(pos-1)/pow2[x]+1;
	int l=pow2[x]*(t-1)+1,r=pow2[x]*t;
	if(rev[x]) change(l+r-pos,k,x-1);
	else change(pos,k,x-1);
	return;
}
ll sum(int l,int r,int x)
{
	if(x<0||l>r) return 0;
	ll res=0;
	int p=(l-1)/pow2[x]+1,q=(r-1)/pow2[x]+1;
	if(l==p&&r==q&&pow2[x]<=r-l+1)
		return bit.query(l,r);
	int L=pow2[x]*(p-1)+1,R=pow2[x]*p,t1,t2;
	t1=l; t2=min(r,R);
	if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
	else res+=sum(t1,t2,x-1);
	if(p!=q){
		L=pow2[x]*(q-1)+1; R=pow2[x]*q;
		t1=max(l,L); t2=r;
		if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
		else res+=sum(t1,t2,x-1);
	}
	return res;
}

int main(void)
{
	scanf("%d%d",&lg,&q);
	n=1<<lg; pow2[0]=1;
	for(int i=1;i<=n;i++)
		bit.tree[i]=0;
	for(int i=1;i<=lg;i++)
		pow2[i]=pow2[i-1]*2;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		bit.add(i,a[i]);
	}
	int opt,x,y;
	while(q--){
		scanf("%d%d",&opt,&x);
		if(opt==1){
			scanf("%d",&y);
			change(x,y,lg);
		}
		if(opt==2) rev[x]^=1;
		if(opt==3){rev[x]^=1; rev[x+1]^=1;}
		if(opt==4){
			scanf("%d",&y);
			printf("%lld\n",sum(x,y,lg));
		}
	}
	return 0;
}
/*
3 8
1 2 3 4 5 6 7 8
2 1
2 3
4 3 5
4 5 7
4 2 5
1 1 999
4 1 1
4 1 2
*/


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long int

int n,q,lg;
int a[262144],pow2[20];
bool rev[20];
struct BIT{
	int tree[262144];
	inline int lb(int x){return x&(-x);}
	inline void add(int x,int y)
	{
		while(x<=n){
			tree[x]+=y;
			x+=lb(x);
		}
		return;
	}
	inline int qry(int r)
	{
		int res=0;
		while(r>0){
			res+=tree[r];
			r-=lb(r);
		}
		return res;
	}
	inline int query(int l,int r)
	{
		return qry(r)-qry(l-1);
	}
}bit;

void change(int pos,int k,int x)
{
	if(x==0){
		bit.add(pos,k-a[pos]);
		a[pos]=k;
		return;
	}
	int t=(pos-1)/pow2[x]+1;
	int l=pow2[x]*(t-1)+1,r=pow2[x]*t;
	if(rev[x]) change(l+r-pos,k,x-1);
	else change(pos,k,x-1);
	return;
}
ll sum(int l,int r,int x)
{
	if(x<0||l>r) return 0;
	ll res=0;
	int p=(l-1)/pow2[x]+1,q=(r-1)/pow2[x]+1;
	if(l==p&&r==q&&pow2[x]<=r-l+1)
		return bit.query(l,r);
	int L=pow2[x]*(p-1)+1,R=pow2[x]*p,t1,t2;
	t1=l; t2=min(r,R);
	if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
	else res+=sum(t1,t2,x-1);
	if(p!=q){
		L=pow2[x]*(q-1)+1; R=pow2[x]*q;
		t1=max(l,L); t2=r;
		if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
		else res+=sum(t1,t2,x-1);
	}
	return res;
}

int main(void)
{
	scanf("%d%d",&lg,&q);
	n=1<<lg; pow2[0]=1;
	for(int i=1;i<=n;i++)
		bit.tree[i]=0;
	for(int i=1;i<=lg;i++)
		pow2[i]=pow2[i-1]*2;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		bit.add(i,a[i]);
	}
	int opt,x,y;
	while(q--){
		scanf("%d%d",&opt,&x);
		if(opt==1){
			scanf("%d",&y);
			change(x,y,lg);
		}
		if(opt==2) rev[x]^=1;
		if(opt==3){rev[x]^=1; rev[x+1]^=1;}
		if(opt==4){
			scanf("%d",&y);
			printf("%lld\n",sum(x,y,lg));
		}
	}
	return 0;
}
/*
3 8
1 2 3 4 5 6 7 8
2 1
2 3
4 3 5
4 5 7
4 2 5
1 1 999
4 1 1
4 1 2
*/


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long int

int n,q,lg;
int a[100001],pow2[20];
bool rev[20];
struct BIT{
	int tree[100001];
	inline int lb(int x){return x&(-x);}
	inline void add(int x,int y)
	{
		while(x<=n){
			tree[x]+=y;
			x+=lb(x);
		}
		return;
	}
	inline int qry(int r)
	{
		int res=0;
		while(r>0){
			res+=tree[r];
			r-=lb(r);
		}
		return res;
	}
	inline int query(int l,int r)
	{
		return qry(r)-qry(l-1);
	}
}bit;

void change(int pos,int k,int x)
{
	if(x==0){
		bit.add(pos,k-a[pos]);
		a[pos]=k;
		return;
	}
	int t=(pos-1)/pow2[x]+1;
	int l=pow2[x]*(t-1)+1,r=pow2[x]*t;
	if(rev[x]) change(l+r-pos,k,x-1);
	else change(pos,k,x-1);
	return;
}
ll sum(int l,int r,int x)
{
	if(x<0||l>r) return 0;
	ll res=0;
	int p=(l-1)/pow2[x]+1,q=(r-1)/pow2[x]+1;
	if(l==p&&r==q&&pow2[x]<=r-l+1)
		return bit.query(l,r);
	int L=pow2[x]*(p-1)+1,R=pow2[x]*p,t1,t2;
	t1=l; t2=min(r,R);
	if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
	else res+=sum(t1,t2,x-1);
	if(p!=q){
		L=pow2[x]*(q-1)+1; R=pow2[x]*q;
		t1=max(l,L); t2=r;
		if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
		else res+=sum(t1,t2,x-1);
	}
	return res;
}

int main(void)
{
	scanf("%d%d",&lg,&q);
	n=1<<lg; pow2[0]=1;
	for(int i=1;i<=n;i++)
		bit.tree[i]=0;
	for(int i=1;i<=lg;i++)
		pow2[i]=pow2[i-1]*2;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		bit.add(i,a[i]);
	}
	int opt,x,y;
	while(q--){
		scanf("%d%d",&opt,&x);
		if(opt==1){
			scanf("%d",&y);
			change(x,y,lg);
		}
		if(opt==2) rev[x]^=1;
		if(opt==3){rev[x]^=1; rev[x+1]^=1;}
		if(opt==4){
			scanf("%d",&y);
			printf("%lld\n",sum(x,y,lg));
		}
	}
	return 0;
}
/*
3 8
1 2 3 4 5 6 7 8
2 1
2 3
4 3 5
4 5 7
4 2 5
1 1 999
4 1 1
4 1 2
*/


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long int

int n,q,lg;
int a[262145],pow2[20];
bool rev[20];
struct BIT{
	int tree[262145];
	inline int lb(int x){return x&(-x);}
	inline void add(int x,int y)
	{
		while(x<=n){
			tree[x]+=y;
			x+=lb(x);
		}
		return;
	}
	inline int qry(int r)
	{
		int res=0;
		while(r>0){
			res+=tree[r];
			r-=lb(r);
		}
		return res;
	}
	inline int query(int l,int r)
	{
		return qry(r)-qry(l-1);
	}
}bit;

void change(int pos,int k,int x)
{
	if(x==0){
		bit.add(pos,k-a[pos]);
		a[pos]=k;
		return;
	}
	int t=(pos-1)/pow2[x]+1;
	int l=pow2[x]*(t-1)+1,r=pow2[x]*t;
	if(rev[x]) change(l+r-pos,k,x-1);
	else change(pos,k,x-1);
	return;
}
ll sum(int l,int r,int x)
{
	if(x<0||l>r) return 0;
	ll res=0;
	int p=(l-1)/pow2[x]+1,q=(r-1)/pow2[x]+1;
	if(l==pow2[x]*(p-1)+1&&r==pow2[x]*q)
		return bit.query(l,r);
	int L=pow2[x]*(p-1)+1,R=pow2[x]*p,t1,t2;
	t1=l; t2=min(r,R);
	if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
	else res+=sum(t1,t2,x-1);
	if(p!=q){
		L=pow2[x]*(q-1)+1; R=pow2[x]*q;
		t1=max(l,L); t2=r;
		if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
		else res+=sum(t1,t2,x-1);
	}
	return res;
}

int main(void)
{
	scanf("%d%d",&lg,&q);
	n=1<<lg; pow2[0]=1;
	for(int i=1;i<=n;i++)
		bit.tree[i]=0;
	for(int i=1;i<=lg;i++)
		pow2[i]=pow2[i-1]*2;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		bit.add(i,a[i]);
	}
	int opt,x,y;
	while(q--){
		scanf("%d%d",&opt,&x);
		if(opt==1){
			scanf("%d",&y);
			change(x,y,lg);
		}
		if(opt==2) rev[x]^=1;
		if(opt==3){rev[x]^=1; rev[x+1]^=1;}
		if(opt==4){
			scanf("%d",&y);
			printf("%lld\n",sum(x,y,lg));
		}
	}
	return 0;
}
/*
3 8
1 2 3 4 5 6 7 8
2 1
2 3
4 3 5
4 5 7
4 2 5
1 1 999
4 1 1
4 1 2
*/


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long int

int n,q,lg;
int a[100001],pow2[20];
bool rev[20];
struct BIT{
	int tree[100001];
	inline int lb(int x){return x&(-x);}
	inline void add(int x,int y)
	{
		while(x<=n){
			tree[x]+=y;
			x+=lb(x);
		}
		return;
	}
	inline int qry(int r)
	{
		int res=0;
		while(r>0){
			res+=tree[r];
			r-=lb(r);
		}
		return res;
	}
	inline int query(int l,int r)
	{
		return qry(r)-qry(l-1);
	}
}bit;

ll sum(int l,int r,int x)
{
	if(x<0||l>r) return 0;
	ll res=0;
	int p=(l-1)/pow2[x]+1,q=(r-1)/pow2[x]+1;
	if(l==p&&r==q)
		return bit.query(l,r);
	int L=pow2[x]*(p-1)+1,R=pow2[x]*p,t1,t2;
	t1=l; t2=min(r,R);
	if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
	else res+=sum(t1,t2,x-1);
	if(p!=q){
		L=pow2[x]*(q-1)+1; R=pow2[x]*q;
		t1=max(l,L); t2=r;
		if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
		else res+=sum(t1,t2,x-1);
	}
	return res;
}

int main(void)
{
	scanf("%d%d",&lg,&q);
	n=1<<lg; pow2[0]=1;
	for(int i=1;i<=n;i++)
		bit.tree[i]=0;
	for(int i=1;i<=lg;i++)
		pow2[i]=pow2[i-1]*2;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		bit.add(i,a[i]);
	}
	int opt,x,y;
	while(q--){
		scanf("%d%d",&opt,&x);
		if(opt==1){
			scanf("%d",&y);
			bit.add(x,y-a[x]);
			a[x]=y;
		}
		if(opt==2) rev[x]^=1;
		if(opt==3){rev[x]^=1; rev[x+1]^=1;}
		if(opt==4){
			scanf("%d",&y);
			printf("%lld\n",sum(x,y,lg));
		}
	}
	return 0;
}
/*
*/


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long int

int n,q,lg;
int a[262145],pow2[20];
bool rev[20];
struct BIT{
	int tree[262145];
	inline int lb(int x){return x&(-x);}
	inline void add(int x,int y)
	{
		while(x<=n){
			tree[x]+=y;
			x+=lb(x);
		}
		return;
	}
	inline ll qry(int r)
	{
		ll res=0;
		while(r>0){
			res+=tree[r];
			r-=lb(r);
		}
		return res;
	}
	inline ll query(int l,int r)
	{
		return qry(r)-qry(l-1);
	}
}bit;

void change(int pos,int k,int x)
{
	if(x==0){
		bit.add(pos,k-a[pos]);
		a[pos]=k;
		return;
	}
	int t=(pos-1)/pow2[x]+1;
	int l=pow2[x]*(t-1)+1,r=pow2[x]*t;
	if(rev[x]) change(l+r-pos,k,x-1);
	else change(pos,k,x-1);
	return;
}
ll sum(int l,int r,int x)
{
	if(x<0||l>r) return 0;
	ll res=0;
	int p=(l-1)/pow2[x]+1,q=(r-1)/pow2[x]+1;
	if(l==pow2[x]*(p-1)+1&&r==pow2[x]*q)
		return bit.query(l,r);
	int L=pow2[x]*(p-1)+1,R=pow2[x]*p,t1,t2;
	t1=l; t2=min(r,R);
	if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
	else res+=sum(t1,t2,x-1);
	if(p!=q){
		L=pow2[x]*(q-1)+1; R=pow2[x]*q;
		t1=max(l,L); t2=r;
		if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
		else res+=sum(t1,t2,x-1);
	}
	return res;
}

int main(void)
{
	scanf("%d%d",&lg,&q);
	n=1<<lg; pow2[0]=1;
	for(int i=1;i<=n;i++)
		bit.tree[i]=0;
	for(int i=1;i<=lg;i++)
		pow2[i]=pow2[i-1]*2;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		bit.add(i,a[i]);
	}
	int opt,x,y;
	while(q--){
		scanf("%d%d",&opt,&x);
		if(opt==1){
			scanf("%d",&y);
			change(x,y,lg);
		}
		if(opt==2) rev[x]^=1;
		if(opt==3){rev[x]^=1; rev[x+1]^=1;}
		if(opt==4){
			scanf("%d",&y);
			printf("%lld\n",sum(x,y,lg));
		}
	}
	return 0;
}
/*
*/


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long int

int n,q,lg;
int a[262145],pow2[20];
bool rev[20];
struct BIT{
	int tree[262145];
	inline int lb(int x){return x&(-x);}
	inline void add(int x,int y)
	{
		while(x<=n){
			tree[x]+=y;
			x+=lb(x);
		}
		return;
	}
	inline int qry(int r)
	{
		int res=0;
		while(r>0){
			res+=tree[r];
			r-=lb(r);
		}
		return res;
	}
	inline int query(int l,int r)
	{
		return qry(r)-qry(l-1);
	}
}bit;

void change(int pos,int k,int x)
{
	if(x==0){
		bit.add(pos,k-a[pos]);
		a[pos]=k;
		return;
	}
	int t=(pos-1)/pow2[x]+1;
	int l=pow2[x]*(t-1)+1,r=pow2[x]*t;
	if(rev[x]) change(l+r-pos,k,x-1);
	else change(pos,k,x-1);
	return;
}
ll sum(int l,int r,int x)
{
	if(x<0||l>r) return 0;
	ll res=0;
	int p=(l-1)/pow2[x]+1,q=(r-1)/pow2[x]+1;
	int L=pow2[x]*(p-1)+1,R=pow2[x]*p,t1,t2;
	if(l==L&&r==R&&pow2[x]<=r-l+1)
		return bit.query(l,r);
	t1=l; t2=min(r,R);
	if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
	else res+=sum(t1,t2,x-1);
	if(p!=q){
		L=pow2[x]*(q-1)+1; R=pow2[x]*q;
		t1=max(l,L); t2=r;
		if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
		else res+=sum(t1,t2,x-1);
	}
	return res;
}

int main(void)
{
	scanf("%d%d",&lg,&q);
	n=1<<lg; pow2[0]=1;
	for(int i=1;i<=n;i++)
		bit.tree[i]=0;
	for(int i=1;i<=lg;i++)
		pow2[i]=pow2[i-1]*2;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		bit.add(i,a[i]);
	}
	int opt,x,y;
	while(q--){
		scanf("%d%d",&opt,&x);
		if(opt==1){
			scanf("%d",&y);
			change(x,y,lg);
		}
		if(opt==2) rev[x]^=1;
		if(opt==3){rev[x]^=1; rev[x+1]^=1;}
		if(opt==4){
			scanf("%d",&y);
			printf("%lld\n",sum(x,y,lg));
		}
	}
	return 0;
}
/*
3 8
1 2 3 4 5 6 7 8
2 1
2 3
4 3 5
4 5 7
4 2 5
1 1 999
4 1 1
4 1 2
*/


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long int

int n,q,lg;
int a[262145],pow2[20];
bool rev[20];
struct BIT{
	ll tree[262145];
	inline int lb(int x){return x&(-x);}
	inline void add(int x,int y)
	{
		while(x<=n){
			tree[x]+=y;
			x+=lb(x);
		}
		return;
	}
	inline ll qry(int r)
	{
		ll res=0;
		while(r>0){
			res+=tree[r];
			r-=lb(r);
		}
		return res;
	}
	inline ll query(int l,int r)
	{
		return qry(r)-qry(l-1);
	}
}bit;

void change(int pos,int k,int x)
{
	if(x==0){
		bit.add(pos,k-a[pos]);
		a[pos]=k;
		return;
	}
	int t=(pos-1)/pow2[x]+1;
	int l=pow2[x]*(t-1)+1,r=pow2[x]*t;
	if(rev[x]) change(l+r-pos,k,x-1);
	else change(pos,k,x-1);
	return;
}
ll sum(int l,int r,int x)
{
	if(x<0||l>r) return 0;
	ll res=0;
	int p=(l-1)/pow2[x]+1,q=(r-1)/pow2[x]+1;
	if(l==pow2[x]*(p-1)+1&&r==pow2[x]*q)
		return bit.query(l,r);
	int L=pow2[x]*(p-1)+1,R=pow2[x]*p,t1,t2;
	t1=l; t2=min(r,R);
	if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
	else res+=sum(t1,t2,x-1);
	if(p!=q){
		L=pow2[x]*(q-1)+1; R=pow2[x]*q;
		t1=max(l,L); t2=r;
		if(rev[x]) res+=sum(R-t2+L,R-t1+L,x-1);
		else res+=sum(t1,t2,x-1);
	}
	return res;
}

int main(void)
{
	scanf("%d%d",&lg,&q);
	n=1<<lg; pow2[0]=1;
	for(int i=1;i<=n;i++)
		bit.tree[i]=0;
	for(int i=1;i<=lg;i++)
		pow2[i]=pow2[i-1]*2;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		bit.add(i,a[i]);
	}
	int opt,x,y;
	while(q--){
		scanf("%d%d",&opt,&x);
		if(opt==1){
			scanf("%d",&y);
			change(x,y,lg);
		}
		if(opt==2) rev[x]^=1;
		if(opt==3){rev[x]^=1; rev[x+1]^=1;}
		if(opt==4){
			scanf("%d",&y);
			printf("%lld\n",sum(x,y,lg));
		}
	}
	return 0;
}
/*
*/


#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int dep[N<<2],tag[N<<2],ls[N<<2],rs[N<<2],sum[N<<2],tot;
void maketag(int p,int t){
	tag[p]^=t;
	if((t>>dep[p])&1) swap(ls[p],rs[p]);
}
void pushup(int p){
	sum[p]=sum[ls[p]]+sum[rs[p]];
}
void pushdown(int p){
	if(tag[p])
		maketag(ls[p],tag[p]),
		maketag(rs[p],tag[p]),
		tag[p]=0;
}
int a[N];
int build(int l,int r,int d){
	int p=++tot;
	dep[p]=d;
	if(l==r) return sum[p]=a[l],p;
	int mid=(l+r)>>1;
	ls[p]=build(l,mid,d-1);
	rs[p]=build(mid+1,r,d-1);
	pushup(p);
	return p;
}
void upt(int p,int l,int r,int pos,int val){
//	cout<<l<<" "<<r<<" "<<sum[p]<<endl;
	if(l==r) return sum[p]=val,void(0);
	pushdown(p);
	int mid=(l+r)>>1;
	if(pos<=mid) upt(ls[p],l,mid,pos,val);
	else upt(rs[p],mid+1,r,pos,val);
	pushup(p);
}
int query(int p,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr) return sum[p];
	pushdown(p);
	int mid=(l+r)>>1,res=0;
	if(ql<=mid) res=query(ls[p],l,mid,ql,qr);
	if(mid+1<=qr) res+=query(rs[p],mid+1,r,ql,qr);
	return res;
}
int main(){
	int n,q;
	cin>>n>>q;
	for(int i=1;i<=(1<<n);++i)
		cin>>a[i];
	int rt=build(1,1<<n,n);
	int opt,x,k;
	while(q--){
		cin>>opt;
		if(opt==1) cin>>x>>k,upt(rt,1,1<<n,x,k);
		if(opt==2) cin>>k,maketag(1,(1<<(k+1))-1);
		if(opt==3) cin>>k,maketag(1,1<<(k+1));
		if(opt==4) cin>>x>>k,cout<<query(1,1,1<<n,x,k)<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e5+5;
int dep[N<<2],tag[N<<2],ls[N<<2],rs[N<<2],sum[N<<2],tot;
void maketag(int p,int t){
	tag[p]^=t;
	if((t>>dep[p])&1) swap(ls[p],rs[p]);
}
void pushup(int p){
	sum[p]=sum[ls[p]]+sum[rs[p]];
}
void pushdown(int p){
	if(tag[p])
		maketag(ls[p],tag[p]),
		maketag(rs[p],tag[p]),
		tag[p]=0;
}
int a[N];
int build(int l,int r,int d){
	int p=++tot;
	dep[p]=d;
	if(l==r) return sum[p]=a[l],p;
	int mid=(l+r)>>1;
	ls[p]=build(l,mid,d-1);
	rs[p]=build(mid+1,r,d-1);
	pushup(p);
	return p;
}
void upt(int p,int l,int r,int pos,int val){
//	cout<<l<<" "<<r<<" "<<sum[p]<<endl;
	if(l==r) return sum[p]=val,void(0);
	pushdown(p);
	int mid=(l+r)>>1;
	if(pos<=mid) upt(ls[p],l,mid,pos,val);
	else upt(rs[p],mid+1,r,pos,val);
	pushup(p);
}
int query(int p,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr) return sum[p];
	pushdown(p);
	int mid=(l+r)>>1,res=0;
	if(ql<=mid) res=query(ls[p],l,mid,ql,qr);
	if(mid+1<=qr) res+=query(rs[p],mid+1,r,ql,qr);
	return res;
}
signed main(){
	int n,q;
	cin>>n>>q;
	for(int i=1;i<=(1<<n);++i)
		cin>>a[i];
	int rt=build(1,1<<n,n);
	int opt,x,k;
	while(q--){
		cin>>opt;
		if(opt==1) cin>>x>>k,upt(rt,1,1<<n,x,k);
		if(opt==2) cin>>k,maketag(1,(1<<(k+1))-1);
		if(opt==3) cin>>k,maketag(1,1<<(k+1));
		if(opt==4) cin>>x>>k,cout<<query(1,1,1<<n,x,k)<<endl;
	}
	return 0;
}


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define LL long long
#define Maxn 300010
using namespace std;
int n,m,flag[Maxn],t[Maxn<<2];
int read()
{
	int x=1,s=0;char ch=getchar();
	while (!isdigit(ch))
	{
		if (ch=='-') x=-1;
		ch=getchar();
	}
	while (isdigit(ch)) s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
	return s*x;
}
void build(int i,int l,int r)
{
	if (l==r) {t[i]=read();return;}
	int mid=(l+r)>>1;
	build(i<<1,l,mid);build(i<<1|1,mid+1,r);
	t[i]=t[i<<1]+t[i<<1|1];
}
void update(int i,int l,int r,int dep,int x,int y)
{
	if (l==r) {t[i]=y;return;}
	int mid=(l+r)>>1;
	if (mid>=x) update(i<<1|flag[dep],l,mid,dep-1,x,y);
	else update(i<<1|(flag[dep]^1),mid+1,r,dep-1,x,y);
	t[i]=t[i<<1]+t[i<<1|1];
}
int query(int i,int l,int r,int dep,int x,int y)
{
	if ((x<=l)&&(r<=y)) return t[i];
	int mid=(l+r)>>1;
	if (mid>=y) return query(i<<1|flag[dep],l,mid,dep-1,x,y);
	else if (mid<x)return query(i<<1|(flag[dep]^1),mid+1,r,dep-1,x,y);
	else return query(i<<1|flag[dep],l,mid,dep-1,x,y)+query(i<<1|(flag[dep]^1),mid+1,r,dep-1,x,y);
}
int main()
{
	n=read(),m=read();
	build(1,1,1<<n);
	for (int i=1;i<=m;i++)
	{
		int opt=read(),x=read();
		if (opt==1)
		{
			int k=read();
			update(1,1,1<<n,n,x,k);
		}
		if (opt==2) for (int i=0;i<=x;i++) flag[i]^=1;
		if (opt==3) flag[x+1]^=1;
		if (opt==4)
		{
			int r=read();
			printf("%d\n",query(1,1,1<<n,n,x,r));
		}
	}
	return 0;
}


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define int long long
#define Maxn 300010
using namespace std;
int n,m,flag[Maxn],t[Maxn<<2];
int read()
{
	int x=1,s=0;char ch=getchar();
	while (!isdigit(ch))
	{
		if (ch=='-') x=-1;
		ch=getchar();
	}
	while (isdigit(ch)) s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
	return s*x;
}
void build(int i,int l,int r)
{
	if (l==r) {t[i]=read();return;}
	int mid=(l+r)>>1;
	build(i<<1,l,mid);build(i<<1|1,mid+1,r);
	t[i]=t[i<<1]+t[i<<1|1];
}
void update(int i,int l,int r,int dep,int x,int y)
{
	if (l==r) {t[i]=y;return;}
	int mid=(l+r)>>1;
	if (mid>=x) update(i<<1|flag[dep],l,mid,dep-1,x,y);
	else update(i<<1|(flag[dep]^1),mid+1,r,dep-1,x,y);
	t[i]=t[i<<1]+t[i<<1|1];
}
int query(int i,int l,int r,int dep,int x,int y)
{
	if ((x<=l)&&(r<=y)) return t[i];
	int mid=(l+r)>>1;
	if (mid>=y) return query(i<<1|flag[dep],l,mid,dep-1,x,y);
	else if (mid<x)return query(i<<1|(flag[dep]^1),mid+1,r,dep-1,x,y);
	else return query(i<<1|flag[dep],l,mid,dep-1,x,y)+query(i<<1|(flag[dep]^1),mid+1,r,dep-1,x,y);
}
signed main()
{
	n=read(),m=read();
	build(1,1,1<<n);
	for (int i=1;i<=m;i++)
	{
		int opt=read(),x=read();
		if (opt==1)
		{
			int k=read();
			update(1,1,1<<n,n,x,k);
		}
		if (opt==2) for (int i=0;i<=x;i++) flag[i]^=1;
		if (opt==3) flag[x+1]^=1;
		if (opt==4)
		{
			int r=read();
			printf("%lld\n",query(1,1,1<<n,n,x,r));
		}
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define min(i, j) (i < j ? i : j)
#define max(i, j) (i > j ? i : j)
const int maxn = 3e6 + 10;
const int maxm = 1e5 + 10;

vector<int> savedep[maxn];

struct TREE{
    int lid[maxn];
    int rid[maxn];
    int tag[maxn];
    ll val[maxn];

    void build(int nowid, int l, int r){
        tag[nowid] = 0;
        int dep = log((r - l + 1)) / log(2);
        savedep[dep].push_back(nowid);
        if(l==r){
            scanf("%lld", &val[nowid]);
            return;
        }
        int mid = (l + r) / 2;
        lid[nowid] = nowid * 2;
        rid[nowid] = nowid * 2 + 1;
        build(lid[nowid], l, mid);
        build(rid[nowid], mid + 1, r);
        val[nowid] = val[lid[nowid]] + val[rid[nowid]];
    }

    inline void pushdown(int nowid){
        if(tag[nowid]){
            tag[nowid] = 0;
            tag[lid[nowid]]++;
            tag[lid[nowid]] %= 2;
            tag[rid[nowid]]++;
            tag[rid[nowid]] %= 2;
            swap(lid[nowid], rid[nowid]);
        }
    }

    ll query(int nowid, int l, int r, int ql, int qr){
        if(ql <= l && r <= qr){
            return val[nowid];
        }
        pushdown(nowid);
        int mid = (l + r) / 2;
        ll res = 0;
        if(ql<=mid){
            res += query(lid[nowid], l, mid, ql, qr);
        }
        if(mid <qr){
            res += query(rid[nowid], mid + 1, r, ql, qr);
        }
        return res;
    }

    void update(int nowid, int l, int r, int pos, ll v){
        if(l==r){
            val[nowid] = v;
            return;
        }
        pushdown(nowid);
        int mid = (l + r) / 2;
        if(pos<=mid){
            update(lid[nowid], l, mid, pos, v);
        }
        else{
            update(rid[nowid], mid + 1, r, pos, v);
        }
        val[nowid] = val[lid[nowid]] + val[rid[nowid]];
    }
} tr;

int main(){
    // freopen("in.txt", "r", stdin);
    int n, q;
    cin >> n >> q;
    int R = 1 << n;
    tr.build(1, 1, R);

    while(q--){
        int t;
        cin >> t;
        if(t==1){
            ll v;
            int p;
            cin >> p >> v;
            tr.update(1, 1, R, p, v);
        }
        if(t==2){
            int k;
            cin >> k;
            for(int id:savedep[k]){
                tr.tag[id]++;
                tr.tag[id] %= 2;
            }
        }
        if(t==3){
            int k;
            cin >> k;
            k++;
            for(int id:savedep[k]){
                swap(tr.lid[id], tr.rid[id]);
            }
        }
        if(t==4){
            int l, r;
            cin >> l >> r;
            // printf("%lld\n", tr.query(1, 1, R, l, r));
            cout << tr.query(1, 1, R, l, r) << endl;
        }
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define min(i, j) (i < j ? i : j)
#define max(i, j) (i > j ? i : j)
const int maxn = 1e6 + 10;
const int maxm = 1e5 + 10;

vector<int> savedep[30];

struct TREE{
    int lid[maxn];
    int rid[maxn];
    int tag[maxn];
    ll val[maxn];
    void init(){
        memset(lid, 0, sizeof(lid));
        memset(rid, 0, sizeof(rid));
        memset(tag, 0, sizeof(tag));
        memset(val, 0, sizeof(val));
    }
    void build(int nowid, int l, int r){
        int dep = log((r - l + 1)) / log(2);
        savedep[dep].push_back(nowid);
        if(l==r){
            scanf("%lld", &val[nowid]);
            return;
        }
        int mid = (l + r) / 2;
        lid[nowid] = nowid * 2;
        rid[nowid] = nowid * 2 + 1;
        build(lid[nowid], l, mid);
        build(rid[nowid], mid + 1, r);
        val[nowid] = val[lid[nowid]] + val[rid[nowid]];
    }

    inline void pushdown(int nowid){
        if(tag[nowid]){
            tag[nowid] = 0;
            tag[lid[nowid]]++;
            tag[lid[nowid]] %= 2;
            tag[rid[nowid]]++;
            tag[rid[nowid]] %= 2;
            swap(lid[nowid], rid[nowid]);
        }
    }

    ll query(int nowid, int l, int r, int ql, int qr){
        if(ql <= l && r <= qr){
            return val[nowid];
        }
        pushdown(nowid);
        int mid = (l + r) / 2;
        ll res = 0;
        if(ql<=mid){
            res += query(lid[nowid], l, mid, ql, qr);
        }
        if(mid <qr){
            res += query(rid[nowid], mid + 1, r, ql, qr);
        }
        return res;
    }

    void update(int nowid, int l, int r, int pos, ll v){
        if(l==r){
            val[nowid] = v;
            return;
        }
        pushdown(nowid);
        int mid = (l + r) / 2;
        if(pos<=mid){
            update(lid[nowid], l, mid, pos, v);
        }
        else{
            update(rid[nowid], mid + 1, r, pos, v);
        }
        val[nowid] = val[lid[nowid]] + val[rid[nowid]];
    }
} tr;

int main(){
    // freopen("in.txt", "r", stdin);
    tr.init();
    int n, q;
    cin >> n >> q;
    int R = 1 << n;
    tr.build(1, 1, R);

    while(q--){
        int t;
        cin >> t;
        if(t==1){
            ll v;
            int p;
            scanf("%d %lld", &p, &v);
            tr.update(1, 1, R, p, v);
        }
        if(t==2){
            int k;
            cin >> k;
            for(int id:savedep[k]){
                tr.tag[id]++;
                tr.tag[id] %= 2;
            }
        }
        if(t==3){
            int k;
            cin >> k;
            k++;
            for(int id:savedep[k]){
                swap(tr.lid[id], tr.rid[id]);
            }
        }
        if(t==4){
            int l, r;
            cin >> l >> r;
            printf("%lld\n", tr.query(1, 1, R, l, r));
        }
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define min(i, j) (i < j ? i : j)
#define max(i, j) (i > j ? i : j)
const int maxn = 3e6 + 10;
const int maxm = 1e5 + 10;

vector<int> savedep[maxn];

struct TREE{
    int lid[maxn];
    int rid[maxn];
    int tag[maxn];
    ll val[maxn];

    void build(int nowid, int l, int r){
        tag[nowid] = 1;
        int dep = log((r - l + 1)) / log(2);
        savedep[dep].push_back(nowid);
        if(l==r){
            scanf("%lld", &val[nowid]);
            return;
        }
        int mid = (l + r) / 2;
        lid[nowid] = nowid * 2;
        rid[nowid] = nowid * 2 + 1;
        build(lid[nowid], l, mid);
        build(rid[nowid], mid + 1, r);
        val[nowid] = val[lid[nowid]] + val[rid[nowid]];
    }

    inline void pushdown(int nowid){
        if(tag[nowid]){
            tag[nowid] = 0;
            tag[lid[nowid]]++;
            tag[lid[nowid]] %= 2;
            tag[rid[nowid]]++;
            tag[rid[nowid]] %= 2;
            swap(lid[nowid], rid[nowid]);
        }
    }

    ll query(int nowid, int l, int r, int ql, int qr){
        if(ql <= l && r <= qr){
            return val[nowid];
        }
        pushdown(nowid);
        int mid = (l + r) / 2;
        ll res = 0;
        if(ql<=mid){
            res += query(lid[nowid], l, mid, ql, qr);
        }
        if(mid <qr){
            res += query(rid[nowid], mid + 1, r, ql, qr);
        }
        return res;
    }

    void update(int nowid, int l, int r, int pos, ll v){
        if(l==r){
            val[nowid] = v;
            return;
        }
        pushdown(nowid);
        int mid = (l + r) / 2;
        if(pos<=mid){
            update(lid[nowid], l, mid, pos, v);
        }
        else{
            update(rid[nowid], mid + 1, r, pos, v);
        }
        val[nowid] = val[lid[nowid]] + val[rid[nowid]];
    }
} tr;

int main(){
    // freopen("in.txt", "r", stdin);
    int n, q;
    cin >> n >> q;
    int R = 1 << n;
    tr.build(1, 1, R);

    while(q--){
        int t;
        cin >> t;
        if(t==1){
            ll v;
            int p;
            cin >> p >> v;
            tr.update(1, 1, R, p, v);
        }
        if(t==2){
            int k;
            cin >> k;
            for(int id:savedep[k]){
                tr.tag[id]++;
                tr.tag[id] %= 2;
            }
        }
        if(t==3){
            int k;
            cin >> k;
            k++;
            for(int id:savedep[k]){
                swap(tr.lid[id], tr.rid[id]);
            }
        }
        if(t==4){
            int l, r;
            cin >> l >> r;
            printf("%lld", tr.query(1, 1, R, l, r));
            // cout << tr.query(1, 1, R, l, r) << endl;
        }
    }
}