Sereja adores trees. Today he came up with a revolutionary new type of binary root trees.His new tree consists of n levels, each vertex is indexed by two integers: the number of the level and the number of the vertex on the current level. The tree root is at level 1, its index is (1, 1). Here is a pseudo code of tree construction.//the global data are integer arrays cnt[], left[][], right[][]cnt[1] = 1;fill arrays left[][], right[][] with values -1;for(level = 1; level < n; level = level + 1){    cnt[level + 1] = 0;    for(position = 1; position <= cnt[level]; position = position + 1){        if(the value of position is a power of two){ // that is, 1, 2, 4, 8...            left[level][position] = cnt[level + 1] + 1;            right[level][position] = cnt[level + 1] + 2;            cnt[level + 1] = cnt[level + 1] + 2;                    }else{            right[level][position] = cnt[level + 1] + 1;            cnt[level + 1] = cnt[level + 1] + 1;        }    }}After the pseudo code is run, cell cnt[level] contains the number of vertices on level level. Cell left[level][position] contains the number of the vertex on the level level + 1, which is the left child of the vertex with index (level, position), or it contains -1, if the vertex doesn't have a left child. Similarly, cell right[level][position] is responsible for the right child. You can see how the tree with n = 4 looks like in the notes.Serja loves to make things complicated, so he first made a tree and then added an empty set A(level, position) for each vertex. Then Sereja executes m operations. Each operation is of one of the two following types:  The format of the operation is "1 t l r x". For all vertices level, position (level = t; l ≤ position ≤ r) add value x to set A(level, position).  The format of the operation is "2 t v". For vertex level, position (level = t, position = v), find the union of all sets of vertices that are in the subtree of vertex (level, position). Print the size of the union of these sets. Help Sereja execute the operations. In this problem a set contains only distinct values like std::set in C++.

The first line contains integers n and m (1 ≤ n, m ≤ 7000).  Next m lines contain the descriptions of the operations. The operation of the first type is given by five integers: 1 t l r x (1 ≤ t ≤ n; 1 ≤ l ≤ r ≤ cnt[t]; 1 ≤ x ≤ 106). The operation of the second type is given by three integers: 2 t v (1 ≤ t ≤ n; 1 ≤ v ≤ cnt[t]).

For each operation of the second type, print the answer on a single line.

NoteYou can find the definitions that are used while working with root trees by this link: http://en.wikipedia.org/wiki/Tree_(graph_theory)You can see an example of a constructed tree at n = 4 below.

import static java.lang.Integer.*;

import java.util.*;

//@SuppressWarnings("unused")
public class B {

	private final static boolean autoflush = false;

	public B () {
		int SZ = 200000;
		int [] X = new int [SZ];
		for (int i = 1, s = 1; i < SZ; ++i, ++s) {
			X[i] = s;
			if (bitCount(i) == 1)
				++s;
		}

		int N = sc.nextInt();
		int M = sc.nextInt();

		List<int []> [] H = new ArrayList[N+1];
		for (int i : req(1, N))
			H[i] = new ArrayList<int []>();

			for (int m : rep(M)) {
				Integer [] Q = sc.nextInts();
				if (Q[0] == 1) {
					int t = Q[1], l = Q[2], r = Q[3], x = Q[4];
					H[t].add(new int [] { l, r, x });
				} else {
					Set<Integer> res = new TreeSet<Integer>();
					int t = Q[1], v = Q[2], w = Q[2];
					for (int y = t; y <= N; ++y, v = X[v], w = X[w+1] - 1)
						for (int [] h : H[y])
							if (h[0] <= w && h[1] >= v)
								res.add(h[2]);
					print(res.size());
				}
			}
	}

	///////////////////////////////////////////////////////////////////////////
	private static int [] rep(int N) { return rep(0, N); }
	private static int [] rep(int S, int T) { if (T <= S) return new int [0]; int [] res = new int [T-S]; for (int i = S; i < T; ++i) res[i-S] = i; return res; }
	private static int [] req(int S, int T) { return rep(S, T+1); }
	////////////////////////////////////////////////////////////////////////////////////
	private final static MyScanner sc = new MyScanner();
	private static class MyScanner {
		public String next() { newLine(); return line[index++]; }
		public int nextInt() { return Integer.parseInt(next()); }
		public String nextLine() { line = null; return readLine(); }
		public String [] nextStrings() { return nextLine().split(" "); }
		public Integer [] nextInts() {
			String [] L = nextStrings();
			Integer [] res = new Integer [L.length];
			for (int i = 0; i < L.length; ++i)
				res[i] = Integer.parseInt(L[i]);
			return res;
		}
		//////////////////////////////////////////////
		private boolean eol() { return index == line.length; }
		private String readLine() {
			try {
				return r.readLine();
			} catch (Exception e) {
				throw new Error (e);
			}
		}
		private final java.io.BufferedReader r;
		private MyScanner () { this(new java.io.BufferedReader(new java.io.InputStreamReader(System.in))); }
		private MyScanner (java.io.BufferedReader r) {
			try {
				this.r = r;
				while (!r.ready())
					Thread.sleep(1);
				start();
			} catch (Exception e) {
				throw new Error(e);
			}
		}
		private String [] line;
		private int index;
		private void newLine() {
			if (line == null || eol()) {
				line = readLine().split(" ");
				index = 0;
			}
		}
	}
	private static void print (Object o, Object... a) { printDelim(" ", o, a); }
	private static void printDelim (String delim, Object o, Object... a) { pw.println(build(delim, o, a)); }
	private static void exit() {
		pw.close();
		System.out.flush();
		System.err.println("------------------");
		System.err.println("Time: " + ((millis() - t) / 1000.0));
		System.exit(0);
	}
	////////////////////////////////////////////////////////////////////////////////////
	private static String build (String delim, Object o, Object... a) {
		StringBuilder b = new StringBuilder();
		append(b, o, delim);
		for (Object p : a)
			append(b, p, delim);
		return b.substring(delim.length());
	}
	private static void append(StringBuilder b, Object o, String delim) {
		if (o.getClass().isArray()) {
			int L = java.lang.reflect.Array.getLength(o);
			for (int i = 0; i < L; ++i)
				append(b, java.lang.reflect.Array.get(o, i), delim);
		} else if (o instanceof Iterable<?>)
			for (Object p : (Iterable<?>)o)
				append(b, p, delim);
		else
			b.append(delim).append(o);
	}
	////////////////////////////////////////////////////////////////////////////////////
	private static void start() { t = millis(); }
	private static java.io.PrintWriter pw = new java.io.PrintWriter(System.out, autoflush);
	private static long t;
	private static long millis() { return System.currentTimeMillis(); }
	public static void main (String[] args) { new B(); exit(); }
}

import java.io.*;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.*;
import java.math.BigInteger;

import static java.lang.Math.*;
import static java.math.BigInteger.*;
import static java.util.Arrays.*;

public class Main{

    void run(){
        boolean oj = System.getProperty("ONLINE_JUDGE") != null;
//        boolean oj = true;
        try{
            if( oj ){
                sc  = new FastScanner( new InputStreamReader(System.in  ) );
                out = new PrintWriter(   new OutputStreamWriter(System.out) );
            } else{
                sc  = new FastScanner(new FileReader("in.txt") );
//                sc  = new FastScanner(new FileReader("D:\\JavaOlymp\\FatalError\\output.txt") );
                out = new PrintWriter(   new FileWriter("out.txt") );
            }
        } catch (Exception e) {
            System.exit(-1);
        }
        long tB = System.currentTimeMillis();
        solve();
        if( !oj ) System.err.println( "Time: " + (System.currentTimeMillis()-tB)/1e3 );
        out.flush();
    }

    class FastScanner{
        BufferedReader br;
        StringTokenizer st = new StringTokenizer("");
        FastScanner( InputStreamReader a ){
            br = new BufferedReader(a);
        }
        FastScanner( FileReader a ){
            br = new BufferedReader(a);
        }
        String next(){
            while( !st.hasMoreTokens() )
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    return null;
                }
            return st.nextToken();
        }
        String readLine(){
            try {
                return br.readLine();
            } catch (Exception e) {
                return null;
            }
        }
        int nextInt(){ return Integer.parseInt(next()); }
    }

    FastScanner sc;
    PrintWriter out;

    public static void main(String[] args){
        new Main().run();
//        new Thread( null, new Runnable() {
//            @Override
//            public void run() {
//                new Main().run();
//            }
//        }, "LOL", (long)1e18 ).run();
    }

    void TLE(){ for(;;); }

    void MLE(){
        int[][] adj = new int[1024*1024][];
        for( int i = 0; i < adj.length; ++i )
            adj[i] = new int[1024*1024];
    }

    void exit( int val ){
        out.flush();
        System.exit(val);
    }
    //////////////////////////////////////////////////////////////////////////////////////////

    class Seg{
        int l, r, val;
        Seg( int _l, int _r, int _val ){
            l   = _l;
            r   = _r;
            val = _val;
        }
    }

    int n;
    int cntQ;
    ArrayList<Seg>[] seg;

    int getAns( int lev, int l, int r ){
        HashSet<Integer> hs = new HashSet<>();
        for( ; lev <= n;  ){
            for( Seg s : seg[lev] )
                if( max(s.l,l) <= min(r,s.r) )
                    hs.add( s.val );
            //
            l = goL(l);
            r = goR(r);
            ++lev;
        }
        return hs.size();
    }

    int f( int pos ){
        int ans = 0;
        for( int p = 0; ; ++p ){
            if( (1<<p) < pos ) ++ans;
            else return ans;
        }
    }

    int goL( int position ){
        int cntPow2 = f(position);
        return 2*cntPow2 + (position-1-cntPow2) + 1;
    }

    int goR( int position ){
        int cntPow2 = f(position);
        return 2*cntPow2 + (position-1-cntPow2) +
                ( Integer.bitCount(position)==1? 2 : 1 );
    }

    void solve(){
//        for( int l = 1; l <= 4; ++l ){
//            for( int p = 1; p <= 7; ++p )
//                out.printf( "%d -> %d %d\n", p, goL(l,p), goR(l,p) );
//            out.println( "--------------" );
//        }

        n = sc.nextInt();
        cntQ = sc.nextInt();

        seg = new ArrayList[n+1];
        for( int i = 1; i <= n; ++i ) seg[i] = new ArrayList<>();

        for( int it = 0; it < cntQ; ++it ){
            int op = sc.nextInt();
            if( op == 1 ){
                int lev = sc.nextInt();
                seg[lev].add(new Seg(sc.nextInt(),sc.nextInt(),sc.nextInt()));
            }
            else if( op == 2 ){
                int lev = sc.nextInt();
                int pos = sc.nextInt();
                out.println(getAns(lev, pos, pos));
            }
            else MLE();
        }

    }

}

import java.io.*;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.*;
import java.math.BigInteger;

import static java.lang.Math.*;
import static java.math.BigInteger.*;
import static java.util.Arrays.*;

public class Main{

    void run(){
        boolean oj = System.getProperty("ONLINE_JUDGE") != null;
//        boolean oj = true;
        try{
            if( oj ){
                sc  = new FastScanner( new InputStreamReader(System.in  ) );
                out = new PrintWriter(   new OutputStreamWriter(System.out) );
            } else{
                sc  = new FastScanner(new FileReader("in.txt") );
//                sc  = new FastScanner(new FileReader("D:\\JavaOlymp\\FatalError\\output.txt") );
                out = new PrintWriter(   new FileWriter("out.txt") );
            }
        } catch (Exception e) {
            System.exit(-1);
        }
        long tB = System.currentTimeMillis();
        solve();
        if( !oj ) System.err.println( "Time: " + (System.currentTimeMillis()-tB)/1e3 );
        out.flush();
    }

    class FastScanner{
        BufferedReader br;
        StringTokenizer st = new StringTokenizer("");
        FastScanner( InputStreamReader a ){
            br = new BufferedReader(a);
        }
        FastScanner( FileReader a ){
            br = new BufferedReader(a);
        }
        String next(){
            while( !st.hasMoreTokens() )
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    return null;
                }
            return st.nextToken();
        }
        String readLine(){
            try {
                return br.readLine();
            } catch (Exception e) {
                return null;
            }
        }
        int nextInt(){ return Integer.parseInt(next()); }
    }

    FastScanner sc;
    PrintWriter out;

    public static void main(String[] args){
        new Main().run();
//        new Thread( null, new Runnable() {
//            @Override
//            public void run() {
//                new Main().run();
//            }
//        }, "LOL", (long)1e18 ).run();
    }

    void TLE(){ for(;;); }

    void MLE(){
        int[][] adj = new int[1024*1024][];
        for( int i = 0; i < adj.length; ++i )
            adj[i] = new int[1024*1024];
    }

    void exit( int val ){
        out.flush();
        System.exit(val);
    }
    //////////////////////////////////////////////////////////////////////////////////////////

    class Seg{
        int l, r, val;
        Seg( int _l, int _r, int _val ){
            l   = _l;
            r   = _r;
            val = _val;
        }
    }

    int n;
    int cntQ;
    ArrayList<Seg>[] seg;

    int sz;
    int[] buf = new int[100_000];
    int getAns( int lev, int l, int r ){
        sz = 0;
        for( ; lev <= n;  ){
            for( Seg s : seg[lev] )
                if( max(s.l,l) <= min(r,s.r) )
                    buf[sz++] = s.val;
            //
            l = goL(l);
            r = goR(r);
            ++lev;
        }
        sort( buf, 0, sz );
        int ans = 0;
        for( int i = 0; i < sz; ++i )
            if( i==0 || buf[i-1]!=buf[i] )
                ++ans;
        return ans;
    }

    int f( int pos ){
        int ans = 0;
        for( int p = 0; ; ++p ){
            if( (1<<p) < pos ) ++ans;
            else return ans;
        }
    }

    int goL( int position ){
        int cntPow2 = f(position);
        return 2*cntPow2 + (position-1-cntPow2) + 1;
    }

    int goR( int position ){
        int cntPow2 = f(position);
        return 2*cntPow2 + (position-1-cntPow2) +
                ( Integer.bitCount(position)==1? 2 : 1 );
    }

    void solve(){
//        for( int l = 1; l <= 4; ++l ){
//            for( int p = 1; p <= 7; ++p )
//                out.printf( "%d -> %d %d\n", p, goL(l,p), goR(l,p) );
//            out.println( "--------------" );
//        }

        n = sc.nextInt();
        cntQ = sc.nextInt();

        seg = new ArrayList[n+1];
        for( int i = 1; i <= n; ++i ) seg[i] = new ArrayList<>();

        for( int it = 0; it < cntQ; ++it ){
            int op = sc.nextInt();
            if( op == 1 ){
                int lev = sc.nextInt();
                seg[lev].add(new Seg(sc.nextInt(),sc.nextInt(),sc.nextInt()));
            }
            else if( op == 2 ){
                int lev = sc.nextInt();
                int pos = sc.nextInt();
                out.println(getAns(lev, pos, pos));
            }
            else MLE();
        }

    }

}

import java.util.*;
import java.io.*;
import java.math.*;

import static java.lang.Math.*;

public class Solution implements Runnable {

	static final int MAX_CNT = 109315;

	public void solve() throws Exception {
		boolean isPowTwo [] = new boolean [MAX_CNT + 1];
		for (int h = 1; h <= MAX_CNT; h *= 2)
			isPowTwo[h] = true;

		int n = sc.nextInt();
		int m = sc.nextInt();

		int p[][] = new int [14][MAX_CNT + 1];
		int prev[] = new int [MAX_CNT + 1];
		int q[] = new int [MAX_CNT + 1];
		q[0] = 2;
		prev[1] = 1;
		prev[2] = 1;
		for (int i = 0; i < 14; i++)
			p[i][1] = 1;
		int head = 0;
		int tail = 1;
		int total = 2;

		while (head < tail) {
			int v = q[head++];
			p[0][v] = prev[v];
			for (int i = 1; i <= 13; i++) {
				p[i][v] = p[i - 1][p[i - 1][v]];
			}
			if (tail + 1 < MAX_CNT) {
				prev[++total] = v;
				q[tail++] = total;
				if (isPowTwo[v] && tail + 1 < MAX_CNT) {
					prev[++total] = v;
					q[tail++] = total;
				}
			}
		}

		int type [] = new int [m];
		int lvl [] = new int [m];
		int l [] = new int [m];
		int r [] = new int [m];
		int x [] = new int [m];

		int exists [] = new int [1000000 + 1];
		Arrays.fill(exists, -1);

		for (int i = 0; i < m; i++) {
			type[i] = sc.nextInt();
			if (type[i] == 1) {
				lvl[i] = sc.nextInt();
				l[i] = sc.nextInt();
				r[i] = sc.nextInt();
				x[i] = sc.nextInt();
			} else {
				int level = sc.nextInt();
				int pos = sc.nextInt();
				int answer = 0;
				for (int j = 0; j < i; j++) {
					if (type[j] == 1 && lvl[j] >= level) {
						int pl = l[j];
						int pr = r[j];
						int dst = lvl[j] - level;
						for (int k = 13; k >= 0 && dst > 0; k--) {
							if ((1 << k) <= dst) {
								dst -= (1 << k);
								pl = p[k][pl];
								pr = p[k][pr];
							}
						}
						if (pl <= pos && pr >= pos && exists[x[j]] != i) {
							exists[x[j]] = i;
							answer++;
						}
					}
				}
				out.println(answer);
			}
		}
	}

	static Throwable t;

	BufferedReader in;
	FastScanner sc;
	PrintWriter out;

	@Override
	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			sc = new FastScanner(in);
			solve();
		} catch (Throwable t) {
			Solution.t = t;
		} finally {
			out.close();
		}
	}

	public static void main(String[] args) throws Throwable {
		Thread thread = new Thread(null, new Solution(), "", 1 << 26);
		thread.start();
		thread.join();
		if (Solution.t != null)
			throw t;
	}

}

class FastScanner {

	BufferedReader in;
	StringTokenizer st;

	public FastScanner(BufferedReader in) {
		this.in = in;
	}

	public String nextToken() throws Exception {
		while (st == null || !st.hasMoreTokens())
			st = new StringTokenizer(in.readLine());
		return st.nextToken();
	}

	public int nextInt() throws Exception {
		return Integer.parseInt(nextToken());
	}

	public long nextLong() throws Exception {
		return Long.parseLong(nextToken());
	}

	public double nextDouble() throws Exception {
		return Double.parseDouble(nextToken());
	}

}

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.TreeSet;
import java.util.StringTokenizer;
import java.util.HashSet;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Zyflair Griffane
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		PandaScanner in = new PandaScanner(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		B solver = new B();
		solver.solve(1, in, out);
		out.close();
	}
}

class B {
    int MAX_SIZE = 200000;
    public void solve(int testNumber, PandaScanner in, PrintWriter out) {
        int[] l = new int[MAX_SIZE];
        int[] r = new int[MAX_SIZE];
        int pow2 = 1;
        int cnt = 1;
        for (int i = 1; i < MAX_SIZE; i++) {
            if (i == pow2) {
                l[i] = cnt++;
                r[i] = cnt++;
                pow2 <<= 1;
            }
            else {
                l[i] = r[i] = cnt++;
            }
        }

        int levels = in.nextInt();
        int queries = in.nextInt();
        TreeSet<Interval> intervals = new TreeSet<>();
        for (int q = 0; q < queries; q++) {
            int type = in.nextInt();
            if (type == 1) {
                intervals.add(new Interval(in.nextInt(), in.nextInt(), in.nextInt(), in.nextInt()));
            }
            else {
                HashSet<Integer> included = new HashSet<>();
                int currLevel = in.nextInt();
                int left = in.nextInt();
                int right = left;
                for (Interval i: intervals) {
                    if (i.level < currLevel) {
                        continue;
                    }
                    while (i.level > currLevel) {
                        left = l[left];
                        right = r[right];
                        currLevel++;
                    }
                    if (right >= i.left && left <= i.right) {
                        included.add(i.value);
                    }
                }
                out.println(included.size());
            }
        }
    }
    public class Interval implements Comparable<Interval> {
        int level;
        int left;
        int right;
        int value;
        public Interval(int level, int left, int right, int value) {
            this.level = level;
            this.left = left;
            this.right = right;
            this.value = value;
        }
        public int compareTo(Interval o) {
            if (level != o.level) {
                return level - o.level;
            }
            if (left != o.left) {
                return left - o.left;
            }
            if (right != o.right) {
                return right - o.right;
            }
            return value - o.value;
        }
    }
}

class PandaScanner {
    public BufferedReader br;
    public StringTokenizer st;
    public InputStream in;

    public PandaScanner(InputStream in) {
        br = new BufferedReader(new InputStreamReader(this.in = in));
    }

    public String nextLine() {
        try {
            return br.readLine();
        }
        catch (Exception e) {
            return null;
        }
    }

    public String next() {
        if (st == null || !st.hasMoreTokens()) {
            st = new StringTokenizer(nextLine().trim());
            return next();
        }
        return st.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    }

import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Random;
import java.io.Writer;
import java.util.List;
import java.io.IOException;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.math.BigInteger;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Egor Kulikov (egor@egork.net)
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		OutputWriter out = new OutputWriter(outputStream);
		TaskB solver = new TaskB();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskB {
    public void solve(int testNumber, InputReader in, OutputWriter out) {
		int count = in.readInt();
		int queryCount = in.readInt();
		int n = 1000000;
		int[] direct = new int[n];
		for (int i = 1; i < n; i++) {
			direct[i] = direct[i - 1] + 1;
			if ((i & (i - 1)) == 0)
				direct[i]++;
		}
		int[][] reverse = new int[20][n];
		int current = 1;
		for (int i = 1; i < n; i++) {
			while (current <= direct[i] && current < n)
				reverse[0][current++] = i;
		}
		for (int i = 1; i < 20; i++) {
			for (int j = 0; j < n; j++)
				reverse[i][j] = reverse[i - 1][reverse[i - 1][j]];
		}
		int[] level = new int[queryCount];
		int[] left = new int[queryCount];
		int[] right = new int[queryCount];
		int[] value = new int[queryCount];
		boolean[] segment = new boolean[queryCount];
		for (int i = 0; i < queryCount; i++) {
			int type = in.readInt();
			if (type == 1) {
				level[i] = in.readInt();
				left[i] = in.readInt();
				right[i] = in.readInt();
				value[i] = in.readInt();
				segment[i] = true;
			} else {
				int cLevel = in.readInt();
				int position = in.readInt();
				IntSet set = new IntHashSet();
				for (int j = 0; j < i; j++) {
					if (segment[j] && level[j] >= cLevel) {
						int delta = level[j] - cLevel;
						int cLeft = left[j];
						int cRight = right[j];
						for (int k = 19; k >= 0; k--) {
							if (delta >= (1 << k)) {
								delta -= 1 << k;
								cLeft = reverse[k][cLeft];
								cRight = reverse[k][cRight];
							}
						}
						if (position >= cLeft && position <= cRight)
							set.add(value[j]);
					}
				}
				out.printLine(set.size());
			}
		}
    }
}

class InputReader {

	private InputStream stream;
	private byte[] buf = new byte[1024];
	private int curChar;
	private int numChars;
	private SpaceCharFilter filter;

	public InputReader(InputStream stream) {
		this.stream = stream;
	}

	public int read() {
		if (numChars == -1)
			throw new InputMismatchException();
		if (curChar >= numChars) {
			curChar = 0;
			try {
				numChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (numChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int readInt() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			if (c < '0' || c > '9')
				throw new InputMismatchException();
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public boolean isSpaceChar(int c) {
		if (filter != null)
			return filter.isSpaceChar(c);
		return isWhitespace(c);
	}

	public static boolean isWhitespace(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	public interface SpaceCharFilter {
		public boolean isSpaceChar(int ch);
	}
}

class OutputWriter {
	private final PrintWriter writer;

	public OutputWriter(OutputStream outputStream) {
		writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
	}

	public OutputWriter(Writer writer) {
		this.writer = new PrintWriter(writer);
	}

	public void close() {
		writer.close();
	}

	public void printLine(int i) {
		writer.println(i);
	}
}

abstract class IntSet extends IntCollection {
	}

class IntHashSet extends IntSet {
	private static final Random RND = new Random();
	private static final int[] SHIFTS = new int[4];
	private static final byte PRESENT_MASK = 1;

	static {
		for (int i = 0; i < 4; i++)
			SHIFTS[i] = RND.nextInt(31) + 1;
	}

	private int size;
	private int[] values;
	private byte[] present;
	private int step;
	private int ratio;

	public IntHashSet() {
		this(3);
	}

	public IntHashSet(int capacity) {
		capacity = Math.max(capacity, 1);
		values = new int[capacity];
		present = new byte[capacity];
		ratio = 2;
		initStep(capacity);
	}

	private void initStep(int capacity) {
		step = RND.nextInt(capacity - 2) + 1;
		while (IntegerUtils.gcd(step, capacity) != 1)
			step++;
	}

	public int size() {
		return size;
	}

	public void add(int value) {
		ensureCapacity((size + 1) * ratio);
		int current = getHash(value);
		while ((present[current] & PRESENT_MASK) != 0) {
			if (values[current] == value)
				return;
			current += step;
			if (current >= values.length)
				current -= values.length;
		}
		present[current] = PRESENT_MASK;
		values[current] = value;
		size++;
	}

	private int getHash(int value) {
		int result = value;
		for (int i : SHIFTS)
			result ^= value >> i;
		result %= values.length;
		if (result < 0)
			result += values.length;
		return result;
	}

	private void ensureCapacity(int capacity) {
		if (values.length < capacity) {
			capacity = Math.max(capacity * 2, values.length);
			rebuild(capacity);
		}
	}

	private void rebuild(int capacity) {
		initStep(capacity);
		int[] oldValues = values;
		byte[] oldPresent = present;
		values = new int[capacity];
		present = new byte[capacity];
		size = 0;
		for (int i = 0; i < oldValues.length; i++) {
			if ((oldPresent[i] & PRESENT_MASK) == PRESENT_MASK)
				add(oldValues[i]);
		}
	}

	}

abstract class IntCollection {
	public abstract int size();
	public abstract void add(int value);

	}

class IntegerUtils {

    public static int gcd(int a, int b) {
        a = Math.abs(a);
        b = Math.abs(b);
        while (b != 0) {
            int temp = a % b;
            a = b;
            b = temp;
        }
        return a;
    }

    }

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.List;

public class B {

	static PrintWriter out;
	static InputReader in;
	static long[] pow = new long[7001];
	public static void main(String[] args) throws Exception {
		in = new InputReader(System.in);
		out = new PrintWriter(System.out);

		int N = in.nextInt();
		int M = in.nextInt();

		List<Segment>[] segments = new List[N+1];
		for(int i=0; i < segments.length; i++) {
			segments[i] = new ArrayList();
		}

		int[] set = new int[1000005];
		for(int qi=0; qi<M;qi++) {
			if(in.nextInt() == 1) {
				int level = in.nextInt();
				long l = in.nextLong();
				long r = in.nextLong();
				int v = in.nextInt();
				segments[level].add(new Segment(l,r,v));
			} else {
				int level = in.nextInt();
				long pos = in.nextLong();
				long l = pos;
				long r = pos;

				int count = 0;
				while(level <= N) {
					for(Segment s : segments[level]) {
						if(s.right >= l && s.left <= r) {
							if(set[s.v] != qi) {
								set[s.v] = qi;
								count++;
							}
						}
					}
					level++;
					l = nextLeft(l);
					r = nextRight(r);
				}
				out.println(count);
			}
		}
		out.close();
	}

	static long nextLeft(long pos) {
		long hi = Long.highestOneBit(pos);
		if(hi == pos) {
			return pos + Long.numberOfTrailingZeros(hi);
		} else {
			return pos + Long.numberOfTrailingZeros(hi) + 1;
		}
	}
	static long nextRight(long pos) {
		return pos + Long.numberOfTrailingZeros(Long.highestOneBit(pos)) + 1;
	}

	static class Segment {
		public long left;
		public long right;
		public int v;
		public Segment(long left, long right, int v) {
			this.left = left;
			this.right = right;
			this.v = v;
		}
	}

	static class InputReader {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;
		private SpaceCharFilter filter;

		public InputReader(InputStream stream) {
			this.stream = stream;
		}

		public int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		public int nextInt() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-') {
				sgn = -1;
				c = read();
			}
			int res = 0;
			do {
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			return res * sgn;
		}

		public long nextLong() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-') {
				sgn = -1;
				c = read();
			}
			long res = 0;
			do {
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			return res * sgn;
		}

		public String nextToken() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public boolean isSpaceChar(int c) {
			if (filter != null)
				return filter.isSpaceChar(c);
			return isWhitespace(c);
		}

		public static boolean isWhitespace(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		public interface SpaceCharFilter {
			public boolean isSpaceChar(int ch);
		}
	}
}

import java.io.*;

import java.awt.geom.Point2D;
import java.text.*;
import java.math.*;
import java.util.*;

public class Main implements Runnable {

	final String filename = "";

	int MAX = 1000001;

	public void solve() throws Exception {
		int n = iread(), m = iread();
		ArrayList<Entry>[] entries = new ArrayList[n];
		for (int i = 0; i < n; i++)
			entries[i] = new ArrayList<Entry>();
		int[] id = new int[MAX];
		for (int i = 0; i < m; i++) {
			int tp = iread();
			if (tp == 1) {
				entries[iread() - 1].add(new Entry(iread(), iread(), iread()));
			} else {
				int res = 0;
				int lvl = iread() - 1;
				int num = iread();
				int left = num, right = num;
				for (; lvl < n; lvl++) {
					for (int j = 0; j < entries[lvl].size(); j++) {
						Entry e = entries[lvl].get(j);
						if (Math.max(e.left, left) <= Math.min(e.right, right)) {
							if (id[e.x] != i + 1) {
								id[e.x] = i + 1;
								res++;
							}
						}
					}
					int l1 = left, r1 = right;
					for (int j = 1; j <= r1; j *= 2) {
						if (j < l1) {
							left++;
							right++;
						} else
							right++;
					}
				}
				out.write(res + "\n");
			}
		}
	}

	class Entry implements Comparable<Entry> {
		int left, right, x;

		@Override
		public int compareTo(Entry o) {
			return x - o.x;
		}

		public Entry(int left, int right, int x) {
			super();
			this.left = left;
			this.right = right;
			this.x = x;
		}

	}

	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new BufferedWriter(new OutputStreamWriter(System.out));
			// in = new BufferedReader(new FileReader(filename+".in"));
			// out = new BufferedWriter(new FileWriter(filename+".out"));
			solve();
			out.flush();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	public int iread() throws Exception {
		return Integer.parseInt(readword());
	}

	public double dread() throws Exception {
		return Double.parseDouble(readword());
	}

	public long lread() throws Exception {
		return Long.parseLong(readword());
	}

	BufferedReader in;

	BufferedWriter out;

	public String readword() throws IOException {
		StringBuilder b = new StringBuilder();
		int c;
		c = in.read();
		while (c >= 0 && c <= ' ')
			c = in.read();
		if (c < 0)
			return "";
		while (c > ' ') {
			b.append((char) c);
			c = in.read();
		}
		return b.toString();
	}

	public static void main(String[] args) {
		try {
			Locale.setDefault(Locale.US);
		} catch (Exception e) {

		}
		// new Thread(new Main()).start();
		new Thread(null, new Main(), "1", 1 << 25).start();
	}
}

import java.io.*;
import java.util.*;

public class SerejaAndTree {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		OutputWriter out = new OutputWriter(outputStream);
		TaskB solver = new TaskB();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskB {
	public void solve(int testNumber, InputReader in, OutputWriter out) {
		int count = in.readInt();
		int queryCount = in.readInt();
		int n = 1000000;
		int[] direct = new int[n];
		for (int i = 1; i < n; i++) {
			direct[i] = direct[i - 1] + 1;
			if ((i & (i - 1)) == 0)
				direct[i]++;
		}
		int[][] reverse = new int[20][n];
		int current = 1;
		for (int i = 1; i < n; i++) {
			while (current <= direct[i] && current < n)
				reverse[0][current++] = i;
		}
		for (int i = 1; i < 20; i++) {
			for (int j = 0; j < n; j++)
				reverse[i][j] = reverse[i - 1][reverse[i - 1][j]];
		}
		int[] level = new int[queryCount];
		int[] left = new int[queryCount];
		int[] right = new int[queryCount];
		int[] value = new int[queryCount];
		boolean[] segment = new boolean[queryCount];
		for (int i = 0; i < queryCount; i++) {
			int type = in.readInt();
			if (type == 1) {
				level[i] = in.readInt();
				left[i] = in.readInt();
				right[i] = in.readInt();
				value[i] = in.readInt();
				segment[i] = true;
			} else {
				int cLevel = in.readInt();
				int position = in.readInt();
				IntSet set = new IntHashSet();
				for (int j = 0; j < i; j++) {
					if (segment[j] && level[j] >= cLevel) {
						int delta = level[j] - cLevel;
						int cLeft = left[j];
						int cRight = right[j];
						for (int k = 19; k >= 0; k--) {
							if (delta >= (1 << k)) {
								delta -= 1 << k;
								cLeft = reverse[k][cLeft];
								cRight = reverse[k][cRight];
							}
						}
						if (position >= cLeft && position <= cRight)
							set.add(value[j]);
					}
				}
				out.printLine(set.size());
			}
		}
	}
}

class InputReader {

	private InputStream stream;
	private byte[] buf = new byte[1024];
	private int curChar;
	private int numChars;
	private SpaceCharFilter filter;

	public InputReader(InputStream stream) {
		this.stream = stream;
	}

	public int read() {
		if (numChars == -1)
			throw new InputMismatchException();
		if (curChar >= numChars) {
			curChar = 0;
			try {
				numChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (numChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int readInt() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			if (c < '0' || c > '9')
				throw new InputMismatchException();
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public boolean isSpaceChar(int c) {
		if (filter != null)
			return filter.isSpaceChar(c);
		return isWhitespace(c);
	}

	public static boolean isWhitespace(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	public interface SpaceCharFilter {
		public boolean isSpaceChar(int ch);
	}
}

class OutputWriter {
	private final PrintWriter writer;

	public OutputWriter(OutputStream outputStream) {
		writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
				outputStream)));
	}

	public OutputWriter(Writer writer) {
		this.writer = new PrintWriter(writer);
	}

	public void close() {
		writer.close();
	}

	public void printLine(int i) {
		writer.println(i);
	}
}

abstract class IntSet extends IntCollection {
}

class IntHashSet extends IntSet {
	private static final Random RND = new Random();
	private static final int[] SHIFTS = new int[4];
	private static final byte PRESENT_MASK = 1;

	static {
		for (int i = 0; i < 4; i++)
			SHIFTS[i] = RND.nextInt(31) + 1;
	}

	private int size;
	private int[] values;
	private byte[] present;
	private int step;
	private int ratio;

	public IntHashSet() {
		this(3);
	}

	public IntHashSet(int capacity) {
		capacity = Math.max(capacity, 1);
		values = new int[capacity];
		present = new byte[capacity];
		ratio = 2;
		initStep(capacity);
	}

	private void initStep(int capacity) {
		step = RND.nextInt(capacity - 2) + 1;
		while (IntegerUtils.gcd(step, capacity) != 1)
			step++;
	}

	public int size() {
		return size;
	}

	public void add(int value) {
		ensureCapacity((size + 1) * ratio);
		int current = getHash(value);
		while ((present[current] & PRESENT_MASK) != 0) {
			if (values[current] == value)
				return;
			current += step;
			if (current >= values.length)
				current -= values.length;
		}
		present[current] = PRESENT_MASK;
		values[current] = value;
		size++;
	}

	private int getHash(int value) {
		int result = value;
		for (int i : SHIFTS)
			result ^= value >> i;
		result %= values.length;
		if (result < 0)
			result += values.length;
		return result;
	}

	private void ensureCapacity(int capacity) {
		if (values.length < capacity) {
			capacity = Math.max(capacity * 2, values.length);
			rebuild(capacity);
		}
	}

	private void rebuild(int capacity) {
		initStep(capacity);
		int[] oldValues = values;
		byte[] oldPresent = present;
		values = new int[capacity];
		present = new byte[capacity];
		size = 0;
		for (int i = 0; i < oldValues.length; i++) {
			if ((oldPresent[i] & PRESENT_MASK) == PRESENT_MASK)
				add(oldValues[i]);
		}
	}
}

abstract class IntCollection {
	public abstract int size();

	public abstract void add(int value);
}

class IntegerUtils {

	public static int gcd(int a, int b) {
		a = Math.abs(a);
		b = Math.abs(b);
		while (b != 0) {
			int temp = a % b;
			a = b;
			b = temp;
		}
		return a;
	}
}

import java.io.*;
import java.util.*;
import java.math.*;

public class B implements Runnable {
	static BufferedReader in;
	static PrintWriter out;
	static StringTokenizer st;
	static Random rnd;

	final int maxValue = 1000000 + 1;

	private void solve() throws IOException {
		int levelsCount = nextInt(), queriesCount = nextInt();
		int alreadyAdd = 0;
		int[] addLevels = new int[queriesCount], addLeftPos = new int[queriesCount], addRightPos = new int[queriesCount], addValue = new int[queriesCount];
		int[] used = new int[maxValue];
		int[] leftBorders = new int[levelsCount + 1], rightBorders = new int[levelsCount + 1];
		int[] powsBefore = new int[maxValue];
		for (int i = 1; i < maxValue; i++) {
			int before = (powsBefore[i - 1]);
			int add = ((i & (i - 1)) == 0) ? 1 : 0;
			powsBefore[i] = before + add;
		}
		for (int i = 0; i < queriesCount; i++) {
			int type = nextInt();
			if (type == 1) {
				addLevels[alreadyAdd] = nextInt();
				addLeftPos[alreadyAdd] = nextInt();
				addRightPos[alreadyAdd] = nextInt();
				addValue[alreadyAdd] = nextInt();
				++alreadyAdd;
			} else {
				int level = nextInt(), pos = nextInt();
				int timer = i + 1;
				int resultSize = 0;
				leftBorders[level] = pos;
				rightBorders[level] = pos;
				for (int j = level; j < levelsCount; j++) {
					leftBorders[j + 1] = leftBorders[j]
							+ powsBefore[leftBorders[j] - 1];
					rightBorders[j + 1] = rightBorders[j]
							+ powsBefore[rightBorders[j]];
				}
				// out.println(Arrays.toString(leftBorders));
				// out.println(Arrays.toString(rightBorders));
				for (int j = 0; j < alreadyAdd; j++) {
					if (addLevels[j] >= level) {
						int leftBorder = leftBorders[addLevels[j]];
						int rightBorder = rightBorders[addLevels[j]];
						if (isInteresect(leftBorder, rightBorder,
								addLeftPos[j], addRightPos[j])
								&& used[addValue[j]] != timer) {
							used[addValue[j]] = timer;
							++resultSize;
						}
					}
				}
				out.println(resultSize);
			}
		}
	}

	private boolean isInteresect(int l0, int r0, int l1, int r1) {
		return (Math.max(l0, l1) <= Math.min(r0, r1));
	}

	public static void main(String[] args) {
		// final boolean oldChecker = false;
		//
		// if (oldChecker)
		// new Thread(null, new Template(), "yarrr", 1 << 24).start();
		// else
		new B().run();
	}

	public void run() {
		try {
			final String className = this.getClass().getName().toLowerCase();

			try {
				in = new BufferedReader(new FileReader(className + ".in"));
				out = new PrintWriter(new FileWriter(className + ".out"));
				// in = new BufferedReader(new FileReader("input.txt"));
				// out = new PrintWriter(new FileWriter("output.txt"));
			} catch (FileNotFoundException e) {
				in = new BufferedReader(new InputStreamReader(System.in));
				out = new PrintWriter(System.out);
			}

			rnd = new Random();

			solve();

			out.close();
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	private String nextToken() throws IOException {
		while (st == null || !st.hasMoreTokens()) {
			String line = in.readLine();

			if (line == null)
				return null;

			st = new StringTokenizer(line);
		}

		return st.nextToken();
	}

	private int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	private long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	private double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ProblemB {

	public static void main(String[] args) throws IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out = new PrintWriter(System.out);
		// D(7000,7000);
		String[] nm = in.readLine().split(" ");
		int n = Integer.valueOf(nm[0]);
		int m = Integer.valueOf(nm[1]);

		int[] parent = new int[210000];
		int[][] child = new int[210000][2];
		int next = 1;
		int cidx = 1;
		for (int i = 1 ; i < parent.length - 10000 ; i++) {
			if (i == next) {
				child[i][0] = cidx;
				child[i][1] = cidx+1;
				parent[cidx] = i;
				parent[cidx+1] = i;
				next *= 2;
				cidx += 2;
			} else {
				child[i][0] = cidx;
				child[i][1] = -1;
				parent[cidx] = i;
				cidx += 1;
			}
		}

		int[] memo = new int[1000100];
		Arrays.fill(memo, -1);

		int[][] query = new int[m][5];
		int lastOneQ = -1;
		int[][] range = new int[n][3];
		for (int i = 0 ; i < n ; i++) {
			Arrays.fill(range[i], -1);
		}
		for (int i = 0 ; i < m ; i++) {
			String[] data = in.readLine().split(" ");
			for (int j = 0 ; j < data.length ; j++) {
				query[i][j] = Integer.valueOf(data[j]);
			}
			if (query[i][0] == 1) {
				lastOneQ = i;
			} else {
				int level = query[i][1]-1;
				int pos = query[i][2];
				int L = pos;
				int R = pos;
				for (int d = level ; d < n ; d++) {
					range[d][0] = L;
					range[d][1] = R;
					range[d][2] = i;
					L = child[L][0];
					R = (child[R][1] == -1) ? child[R][0] : child[R][1];
				}
				int ans = 0;
				for (int j = lastOneQ ; j >= 0 ; j--) {
					if (query[j][0] == 1) {
						int ql = query[j][1]-1;
						if (range[ql][2] == i) {
							int fr = query[j][2];
							int to = query[j][3];
							int v = query[j][4];
							if (memo[v] != i && intersect(fr, to, range[ql][0], range[ql][1])) {
								ans++;
								memo[v] = i;
							}
						}
					}
				}
				out.println(ans);
			}
		}
		out.flush();
	}

	private static boolean intersect(int A, int B, int C, int D) {
		return (B >= C && D >= A);
	}

	private static void D(int n, int m) {
		System.out.println(n + " " + m);
		for (int i = 1 ; i <= m/2 ; i++) {
			System.out.println("1 " + i + " 1 " + i + " 1");
		}
		for (int i = m/2 ; i < m ; i++) {
			System.out.println("2 1 1");
		}
	}

	public static void debug(Object... o) {
		System.err.println(Arrays.deepToString(o));
	}
}

import java.util.List;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Set;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.util.HashSet;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		FastScanner in = new FastScanner(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskB solver = new TaskB();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskB {
	public void solve(int testNumber, FastScanner in, PrintWriter out) {
		int n = in.nextInt();
		int numQueries = in.nextInt();
		List<Segment>[] atLevel = new List[n + 1];
		for (int i = 0; i < n + 1; i++) {
			atLevel[i] = new ArrayList<Segment>();
		}
		for (int query = 0; query < numQueries; query++) {
			int type = in.nextInt();
			int level = in.nextInt();
			if (type == 1) {
				Segment s = new Segment();
				s.l = in.nextInt();
				s.r = in.nextInt();
				s.x = in.nextInt();
				atLevel[level].add(s);
			} else {
				int v = in.nextInt();
				Set<Integer> set = new HashSet<Integer>();
				int l = v;
				int r = v;
				while (level <= n) {
					for (Segment s : atLevel[level]) {
						int ll = Math.max(l, s.l);
						int rr = Math.min(r, s.r);
						if (ll <= rr) {
							set.add(s.x);
						}
					}
					l = goLeft(l);
					r = goRight(r);
					++level;
				}
				out.println(set.size());
			}
		}
	}

	private int goLeft(int x) {
		int p2before = 0;
		for (int i = 0; (1<<i) < x; i++) {
			++p2before;
		}
		int y = x + p2before;
		return y;
	}

	private int goRight(int x) {
		int y = goLeft(x);
		if ((x & (x - 1)) == 0) {
			return y + 1;
		}
		return y;
	}

	class Segment {
		int l, r, x;
	}
}

class FastScanner {

	private BufferedReader in;
	private StringTokenizer st;

	public FastScanner(InputStream stream) {
		in = new BufferedReader(new InputStreamReader(stream));
	}

	public String next() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(in.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return st.nextToken();
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	}

//package round222;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.InputMismatchException;
import java.util.List;

public class B {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	public static int[] shrink(int[] a)
	{
		int n = a.length;
		long[] b = new long[n];
		for(int i = 0;i < n;i++)b[i] = (long)a[i]<<32|i;
		Arrays.sort(b);
		int[] ret = new int[n];
		int p = 0;
		for(int i = 0;i < n;i++) {
			if(i>0 && (b[i]^b[i-1])>>32!=0)p++;
			ret[(int)b[i]] = p;
		}
		return ret;
	}

	void solve()
	{
		int[] map = new int[200001];
		for(int i = 1;i <= 200000;i++){
			map[i] = map[i-1] + ((i&i-1) == 0 ? 2 : 1);
		}

		int n = ni(), m = ni();
		int[][] q = new int[m][];
		int[] xs = new int[m];
		int p = 0;
		for(int i = 0;i < m;i++){
			int t = ni();
			if(t == 1){
				q[i] = new int[]{1, ni(), ni(), ni(), ni()};
				xs[p++] = q[i][4];
			}else{
				q[i] = new int[]{2, ni(), ni()};
			}
		}
		xs = shrink(xs);
		p = 0;
		for(int i = 0;i < m;i++){
			if(q[i][0] == 1){
				q[i][4] = xs[p++];
			}
		}

		List<List<int[]>> list = new ArrayList<List<int[]>>();
		for(int i = 0;i <= n;i++)list.add(new ArrayList<int[]>());
		for(int i = 0;i < m;i++){
			if(q[i][0] == 2){
				BitSet bs = new BitSet();
				int L = q[i][2]-1, R = q[i][2];
				for(int j = q[i][1];j <= n;j++){
					for(int[] r : list.get(j)){
//						tr(r, L, R);
						if(Math.max(r[0], L) < Math.min(r[1], R)){
							bs.set(r[2]);
						}
					}
					L = map[L]; R = map[R];
				}
				out.println(bs.cardinality());
			}else if(q[i][0] == 1){
				list.get(q[i][1]).add(new int[]{q[i][2]-1, q[i][3], q[i][4]});
			}
		}
	}

	void run() throws Exception
	{
//		int n = 7000, m = 7000;
//		Random gen = new Random();
//		StringBuilder sb = new StringBuilder();
//		sb.append(n + " ");
//		sb.append(m + " ");
//		for(int i = 0;i < n;i++){
//			if(gen.nextInt(2) == 0){
//				sb.append(1 + " ");
//				sb.append(gen.nextInt(n)+1 + " ");
//				int a = gen.nextInt(n)+1;
//				int b = gen.nextInt(n)+1;
//				sb.append(Math.min(a, b) + " ");
//				sb.append(Math.max(a, b) + " ");
//				sb.append(gen.nextInt(1000000)+1 + " ");
//			}else{
//				sb.append(2 + " ");
//				sb.append(gen.nextInt(n)+1 + " ");
//				sb.append(gen.nextInt(n)+1 + " ");
//			}
//		}
//		INPUT = sb.toString();

		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new B().run(); }

	private byte[] inbuf = new byte[1024];
	private int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}

import java.io.*;
import java.util.*;

public class Main223B {

    private FastScanner in;
    private PrintWriter out;

    class Oper {
        int type;
        int level;
        int left;
        int right;
        int value;
        int position;
    }
    public void solve() throws IOException {
        int C = in.nextInt();
        int N = countLeaves(C);
        int[] parent = new int[N + 1];
        parent[1] = 1;
        int next = 2;
        int currParent = 1;
        int nextPow2 = 2;
        while(next <= N) {
            parent[next] = currParent;
            next++;
            if(currParent == nextPow2) {
                parent[next] = currParent;
                next++;
                nextPow2 *= 2;
            }
            currParent++;
        }

        int M = in.nextInt();
        Oper[] ops = new Oper[M];
        for(int i = 0; i < M; i++) {
            Oper op = new Oper();
            op.type = in.nextInt();
            if(op.type == 1) {
                op.level = in.nextInt();
                op.left = in.nextInt();
                op.right = in.nextInt();
                op.value = in.nextInt();
            }
            else {
                op.level = in.nextInt();
                op.position = in.nextInt();
            }
            ops[i] = op;
        }

        Map<Integer, Map<Integer, Map<Integer, HashSet<Integer>>>> maps =
                new HashMap<Integer, Map<Integer, Map<Integer, HashSet<Integer>>>>();
        for(int i = M - 1; i >= 0; i--) {
            Oper op = ops[i];
            if(op.type == 2) {
                Map<Integer, Map<Integer, HashSet<Integer>>> ml = maps.get(op.level);
                if(ml == null) {
                    ml = new HashMap<Integer, Map<Integer, HashSet<Integer>>>();
                    maps.put(op.level, ml);
                }
                Map<Integer, HashSet<Integer>> hm = ml.get(op.position);
                if(hm == null) {
                    hm = new HashMap<Integer, HashSet<Integer>>();
                    ml.put(op.position, hm);
                }
                hm.put(i, new HashSet<Integer>());
            }
            else {
                int left = op.left;
                int right = op.right;
                for(int j = op.level; j >= 1; j--) {
                    Map<Integer, Map<Integer, HashSet<Integer>>> ml = maps.get(j);
                    if(ml != null) {
                        for(Map.Entry<Integer, Map<Integer, HashSet<Integer>>> e : ml.entrySet()) {
                            if(e.getKey() >= left && e.getKey() <= right) {
                                Map<Integer, HashSet<Integer>> m = e.getValue();
                                for(HashSet<Integer> set : m.values()){
                                    set.add(op.value);
                                }
                            }
                        }
                    }
                    left = parent[left];
                    right = parent[right];
                }
            }
        }
        for(int i = 0; i < M; i++) {
            Oper op = ops[i];
            if(op.type == 2) {
                out.println(maps.get(op.level).get(op.position).get(i).size());
            }
        }
    }

    private int countLeaves(int level) {
        level--;
        int count = 1;
        int add = 1;
        while(level > 0) {
            int next = 1 << add;
            int d = next - count;
            int l = d / add;
            if(d % add != 0) {
                l++;
            }
            l = Math.min(l, level);
            level -= l;
            count += l * add;
            add++;
        }
        return count;
    }

    public void run() {
        try {
            in = new FastScanner(System.in);
            out = new PrintWriter(System.out);
            solve();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    class FastScanner {

        BufferedReader br;
        StringTokenizer st;

        FastScanner(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }
    }

    public static void main(String[] arg) {
        new Main223B().run();
    }
}

import java.io.*;
import java.util.*;

public class B {

    BufferedReader br;
    PrintWriter out;
    StringTokenizer st;
    boolean eof;

    int f(int x) {
        int ret = 0;
        while (x > 0) {
            ret++;
            x >>= 1;
        }
        return ret;
    }

    boolean isPow2(int x) {
        if (x == 0) {
            throw new AssertionError();
        }
        return (x & (x - 1)) == 0;
    }

    void solve() throws IOException {
        int n = nextInt();
        int q = nextInt();

        int[] sz = new int[n + 1];
        sz[1] = 1;
        for (int i = 1; i < n; i++) {
            sz[i + 1] = sz[i] + f(sz[i]);
        }

        int[] up = new int[sz[n] + 1];

        for (int par = 1, child = 1; child <= sz[n]; par++) {
            up[child++] = par;
            if (isPow2(par)) {
                if (child <= sz[n]) {
                    up[child++] = par;
                }
            }
        }

        List<int[]> add = new ArrayList<>();
        List<int[]> ans = new ArrayList<>();

        for (int i = 0; i < q; i++) {
            int type = nextInt();
            if (type == 1) {
                int[] tmp = { nextInt(), nextInt(), nextInt(), nextInt(), i };
                add.add(tmp);
            } else {
                int[] tmp = { nextInt(), nextInt(), i };
                ans.add(tmp);
            }
        }

        int[] outp = new int[ans.size()];
        Set<Integer> set = new HashSet<>();

        for (int level = n; level >= 1; level--) {
            for (int i = 0; i < ans.size(); i++) {
                if (ans.get(i)[0] == level) {
                    set.clear();
                    int pos = ans.get(i)[1];
                    int when = ans.get(i)[2];
                    for (int j = 0; j < add.size(); j++) {
                        int[] tmp = add.get(j);
                        // System.err.println(Arrays.toString(tmp));
                        if (tmp[0] == level && tmp[1] <= pos && pos <= tmp[2] && when > tmp[4]) {
                            set.add(tmp[3]);
                        }
                    }
                    outp[i] = set.size();
                }
            }

            for (int i = 0; i < add.size(); i++) {
                int[] tmp = add.get(i);
                if (tmp[0] == level) {
                    tmp[0]--;
                    tmp[1] = up[tmp[1]];
                    tmp[2] = up[tmp[2]];
                }
            }

        }

        for (int x : outp) {
            out.println(x);
        }

    }

    B() throws IOException {
        br = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);
        solve();
        out.close();
    }

    public static void main(String[] args) throws IOException {
        new B();
    }

    String nextToken() {
        while (st == null || !st.hasMoreTokens()) {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (Exception e) {
                eof = true;
                return null;
            }
        }
        return st.nextToken();
    }

    String nextString() {
        try {
            return br.readLine();
        } catch (IOException e) {
            eof = true;
            return null;
        }
    }

    int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }

    long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }

    double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }
}

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.StringTokenizer;
import java.util.HashSet;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Agostinho Junior
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		OutputWriter out = new OutputWriter(outputStream);
		TaskD solver = new TaskD();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskD {
	OutputWriter out;
	InputReader in;
	public void solve(int testNumber, InputReader in, OutputWriter out) {
		this.in = in; this.out = out;
		int n = in.readInt();
		final int maxSize = (int)2e5;
		int[] min = new int[maxSize];
		int[] max = new int[maxSize];
		min[1] = 1;
		max[1] = 2;
		int start = 2;
		int end = 2;
		for (int i = 2; i < n; i++) {
			int tempEnd = end;
			for (int j = start; j <= end; j++) {
				if ((j & (j - 1)) == 0) {
					int a = end + tempEnd - end + 1;
					int b = end + tempEnd - end + 2;
					min[j] = a;
					max[j] = b;
					tempEnd += 2;
				} else {
					int a = end + tempEnd - end + 1;
					min[j] = max[j] = a;
					tempEnd++;
				}
			}
			start = end + 1;
			end = tempEnd;
		}
		int m = in.readInt();
		ArrayList<Insertion> insertions = new ArrayList<Insertion>();
		HashSet<Integer> set = new HashSet<Integer>();
		int[] levelStart = new int[n + 1];
		int[] levelEnd = new int[n + 1];
		while (m-- > 0) {
			switch (in.readInt()) {
				case 1:
					insertions.add(new Insertion(in));
					break;
				case 2:
					int level = in.readInt();
					int pos = in.readInt();
					levelStart[level] = pos;
					levelEnd[level] = pos;
					for (int t = level; t < n; t++) {
						levelStart[t + 1] = min[levelStart[t]];
						levelEnd[t + 1] = max[levelEnd[t]];
					}
					set.clear();
					for (Insertion ins: insertions) {
						int t = ins.level;
						int s = ins.start;
						int e = ins.end;
						if (level <= t && levelStart[t] <= e && s <= levelEnd[t]) {
							set.add(ins.x);
						}
					}
					out.println(set.size());
					break;
			}
		}
	}
}

class Insertion {
	final int level;
	final int start;
	final int end;
	final int x;
	public Insertion(InputReader in) {
		level = in.readInt();
		start = in.readInt();
		end = in.readInt();
		x = in.readInt();
	}
}

class OutputWriter {
	private PrintWriter output;
	public OutputWriter() {
		this(System.out);
	}
	public OutputWriter(OutputStream out) {
		output = new PrintWriter(out);
	}
	public OutputWriter(Writer writer) {
		output = new PrintWriter(writer);
	}
	public void println(Object o) {
		output.println(o);
	}
	public void close() {
		output.close();
	}
}

class InputReader {
	private BufferedReader input;
	private StringTokenizer line = new StringTokenizer("");
	public InputReader() {
		this(System.in);
	}
	public InputReader(InputStream in) {
		input = new BufferedReader(new InputStreamReader(in));
	}
	public InputReader(String s) {
		try {
			input = new BufferedReader(new FileReader(s));
		} catch(IOException io) { io.printStackTrace(); System.exit(0);}
	}
	public void fill() {
		try {
			if(!line.hasMoreTokens()) line = new StringTokenizer(input.readLine());
		} catch(IOException io) { io.printStackTrace(); System.exit(0);}
	}
	public int readInt() {
		fill();
		return Integer.parseInt(line.nextToken());
	}
}

import java.io.*;
import java.util.*;

public class Main {
    static class Interval {
        public int from;
        public int to;
        public int value;
        public Interval(int from, int to, int value) {
            this.from = from;
            this.to = to;
            this.value = value;
        }
        public boolean intersect(int from, int to) {
            if (this.from >= to || this.to <= from) {
                return false;
            } else {
                return true;
            }
        }
    }

    public static void main(String[] args) throws Exception {
        FastScanner scan = new FastScanner(System.in);
        int n = scan.nextInt();
        int m = scan.nextInt();
        ArrayList<ArrayList<Interval>> records = new ArrayList<ArrayList<Interval>>();
        for (int i = 0; i < n; i++) {
            records.add(new ArrayList<Interval>());
        }

        HashSet<Integer> checker = new HashSet<Integer>();
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < m; ++i) {
            if (scan.nextInt() == 1) {
                int t = scan.nextInt() - 1;
                int l = scan.nextInt() - 1;
                int r = scan.nextInt();
                int value = scan.nextInt();
                records.get(t).add(new Interval(l, r, value));
            } else {
                int t = scan.nextInt() - 1;
                int from = scan.nextInt() - 1;
                int to = from + 1;
                for (int level = t; level < n; ++level) {
                    for (Interval interval : records.get(level)) {
                        if (interval.intersect(from, to)) {
                            checker.add(interval.value);
                        }
                    }
                    int left = 0, right = 0;
                    for (int shift = 0; shift < 30; shift++) {
                        if (from >= 1 << shift) {
                            left = shift + 1;
                        }
                        if (to >= 1 << shift) {
                            right = shift + 1;
                        } else {
                            break;
                        }
                    }
                    from = from + left;
                    to = to + right;
                }
                builder.append(Integer.toString(checker.size()));
                checker.clear();
                builder.append('\n');
            }
        }
        System.out.print(builder.toString());
        System.out.flush();
    }
}

class FastScanner {
    BufferedReader in;
    StringTokenizer tok;

    public FastScanner(InputStream in) {
        this.in = new BufferedReader(new InputStreamReader(in));
        tok = new StringTokenizer("");
    }

    private String tryReadNextLine() {
        try {
            return in.readLine();
        } catch (Exception e) {
            throw new InputMismatchException();
        }
    }

    public String nextToken() {
        while (!tok.hasMoreTokens()) {
            tok = new StringTokenizer(next());
        }
        return tok.nextToken();
    }

    public String next() {
        String newLine = tryReadNextLine();
        if (newLine == null)
            throw new InputMismatchException();
        return newLine;
    }

    public int nextInt() {
        return Integer.parseInt(nextToken());
    }

    public long nextLong() {
        return Long.parseLong(nextToken());
    }

}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;

public class D {

    static int log2(int i) {
        int ret=0;
        while(i>0) {
            ret++;
            i=i>>1;
        }
        return ret;
    }

    static void compute(int n, int[][] q) {
        //group queries by level
        int[] l2qcnt=new int[n+1];
        for (int i=0; i<q.length; i++) {
            if(q[i][0]==1) {
                l2qcnt[q[i][1]]++;
            }
        }
        int[][] l2q=new int[n+1][];
        for (int i=1; i<=n; i++) {
            l2q[i]=new int[l2qcnt[i]];
        }
        Arrays.fill(l2qcnt, 0);
        //end group queries by level

        imap s=new imap();
        for (int i=0; i<q.length; i++) {
            int lvl=q[i][1];
            if(q[i][0]==1) {
                l2q[lvl][l2qcnt[lvl]++]=i;
            } else {
                s.clear();
                int l=q[i][2], r=l;
                for (int j=lvl; j<=n; j++) {
                    for (int k=0; k<l2qcnt[j]; k++) {
                        int qidx=l2q[j][k];
                        int ql=q[qidx][2];
                        int qr=q[qidx][3];
                        if(!(r<ql||l>qr)) {
                            s.put(q[qidx][4],0);
                        }
                    }
                    //update l,r
                    int extra=Integer.bitCount(r)==1? 1: 0;
                    l+=log2(l-1);
                    r+=log2(r-1);
                    r+=extra;
                }
                System.out.println(s.size);
            }
        }
    }

    static StringBuilder sb=new StringBuilder();
    static void parse(String l, int[] here) {
        sb.setLength(0);
        int len=l.length(), j=0;
        for (int i=0; i<len; i++) {
            char c=l.charAt(i);
            if(c==' ') {
                here[j++]=Integer.parseInt(sb.toString());
                sb.setLength(0);
            } else {
                sb.append(c);
            }
        }
        if(sb.length()>0) {
            here[j++]=Integer.parseInt(sb.toString());
        }
    }

    static void run_stream(InputStream ins) throws IOException {
        BufferedReader r=new BufferedReader(new InputStreamReader(System.in));
        String[] l=r.readLine().split(" ");
        int n=Integer.parseInt(l[0]);
        int m=Integer.parseInt(l[1]);

        int[][] q=new int[m][5];
        for (int i=0; i<m; i++) {
            parse(r.readLine(), q[i]);
            //q[i][1]--;
        }

        compute(n, q);
    }

    public static void main(String[] args) throws IOException {
        run_stream(System.in);
    }

    public static class imap {
        public int size=0;
        float load_factor;

        public int[]
                bucket2idx,
                idx2k,
                idx2v,
                idx2n;

        public imap() {
            this(8, 0.75f);
        }

        public imap(int capacity, float load_factor) {
            this.load_factor=load_factor;
            bucket2idx=new int[capacity];
            Arrays.fill(bucket2idx, -1);

            int data_size=(int)(capacity*load_factor)+1;
            idx2k=new int[data_size];
            idx2v=new int[data_size];
            idx2n=new int[data_size];
        }

        private int i2hash(int i) {
            i^=(i>>>20)^(i>>>12);
            return i^(i>>>7)^(i>>>4);
        }

        public boolean contains(int k) {
            int idx=bucket2idx[k2bucket(k)];
            while(idx>=0) {
                if(idx2k[idx]==k) {
                    return true;
                } else {
                    idx=idx2n[idx];
                }
            }
            return false;
        }

        public int get(int k) {
            int idx=bucket2idx[k2bucket(k)];
            while(idx>=0) {
                if(idx2k[idx]==k) {
                    return idx2v[idx];
                } else {
                    idx=idx2n[idx];
                }
            }
            throw new IndexOutOfBoundsException();
        }

        public int put(int k, int v) {
            if(size>(int)(bucket2idx.length*load_factor)) {
                rehash(bucket2idx.length<<1);
            }

            int bucket_idx=k2bucket(k);
            int idx=bucket2idx[bucket_idx];
            if(idx>=0) {
                while(true) {
                    if(idx2k[idx]==k) {
                        int oldv=idx2v[idx];
                        idx2v[idx]=v;
                        return oldv;
                    } else if(idx2n[idx]<0) {
                        int idx2=size++;
                        idx2k[idx2]=k;
                        idx2v[idx2]=v;
                        idx2n[idx]=idx2;
                        idx2n[idx2]=-1;
                        return v;
                    } else {
                        idx=idx2n[idx];
                    }
                }
            } else {
                idx=size++;
                bucket2idx[bucket_idx]=idx;
                idx2k[idx]=k;
                idx2v[idx]=v;
                idx2n[idx]=-1;
                return v;
            }
        }

        protected int k2bucket(int k) {
            int bucket_idx=i2hash(k)%bucket2idx.length;
            if(bucket_idx<0) {
                bucket_idx=bucket2idx.length+bucket_idx;
            }
            return bucket_idx;
        }

        void rehash(int new_capacity) {
            int[] _bucket2idx=new int[new_capacity];
            Arrays.fill(_bucket2idx, -1);

            int data_size=(int)(new_capacity*load_factor)+1;
            int[] _idx2k=new int[data_size];
            int[] _idx2v=new int[data_size];
            int[] _idx2n=new int[data_size];

            int old_size=size;
            size=0;
            //swap
            int[] aux=_bucket2idx; _bucket2idx=bucket2idx; bucket2idx=aux;
            aux=_idx2k; _idx2k=idx2k; idx2k=aux;
            aux=_idx2v; _idx2v=idx2v; idx2v=aux;
            aux=_idx2n; _idx2n=idx2n; idx2n=aux;
            //populate
            for(int i=0; i<old_size; i++) {
                put(_idx2k[i], _idx2v[i]);
            }
        }

        public void clear() {
            if(size>0) {
                size=0;
                Arrays.fill(bucket2idx, -1);
            }
        }

        public void putAll(imap m) {
            int new_size=size+m.size;
            if(new_size>(int)(bucket2idx.length*load_factor)) {
                rehash((int)(1+new_size/load_factor));
            }
            for(int idx=0; idx<m.size; idx++) {
                put(m.idx2k[idx], m.idx2v[idx]);
            }
        }

        public String toString() {
            if(size==0)
                return "{}";

            StringBuilder sb=new StringBuilder();
            sb.append('{');
            for(int i=0; i<size; i++) {
                sb.append(idx2k[i]);
                sb.append('=');
                sb.append(idx2v[i]);
                if(i<size-1) {
                    sb.append(", ");
                }
            }
            return sb.append('}').toString();
        }
    }

}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;

public class D {

    static int log2(int i) {
        int ret=0;
        while(i>0) {
            ret++;
            i=i>>1;
        }
        return ret;
    }

    static void compute(int n, int[][] q) {
        //group queries by level
        int[] l2qcnt=new int[n+1];
        for (int i=0; i<q.length; i++) {
            if(q[i][0]==1) {
                l2qcnt[q[i][1]]++;
            }
        }
        int[][] l2q=new int[n+1][];
        for (int i=1; i<=n; i++) {
            l2q[i]=new int[l2qcnt[i]];
        }
        Arrays.fill(l2qcnt, 0);
        //end group queries by level

        int[] s=new int[1000000];
        for (int i=0; i<q.length; i++) {
            int ret=0;
            int lvl=q[i][1];
            if(q[i][0]==1) {
                l2q[lvl][l2qcnt[lvl]++]=i;
            } else {
                int l=q[i][2], r=l;
                for (int j=lvl; j<=n; j++) {
                    for (int k=0; k<l2qcnt[j]; k++) {
                        int qidx=l2q[j][k];
                        int ql=q[qidx][2];
                        int qr=q[qidx][3];
                        if(!(r<ql||l>qr)) {
                            int x=q[qidx][4];
                            if(s[x]!=i+1) {
                                ret++;
                                s[x]=i+1;
                            }
                        }
                    }
                    //update l,r
                    int extra=Integer.bitCount(r)==1? 1: 0;
                    l+=log2(l-1);
                    r+=log2(r-1);
                    r+=extra;
                }
                System.out.println(ret);
            }
        }
    }

    static StringBuilder sb=new StringBuilder();
    static void parse(String l, int[] here) {
        sb.setLength(0);
        int len=l.length(), j=0;
        for (int i=0; i<len; i++) {
            char c=l.charAt(i);
            if(c==' ') {
                here[j++]=Integer.parseInt(sb.toString());
                sb.setLength(0);
            } else {
                sb.append(c);
            }
        }
        if(sb.length()>0) {
            here[j++]=Integer.parseInt(sb.toString());
        }
    }

    static void run_stream(InputStream ins) throws IOException {
        BufferedReader r=new BufferedReader(new InputStreamReader(System.in));
        String[] l=r.readLine().split(" ");
        int n=Integer.parseInt(l[0]);
        int m=Integer.parseInt(l[1]);

        int[][] q=new int[m][5];
        for (int i=0; i<m; i++) {
            parse(r.readLine(), q[i]);
        }

        compute(n, q);
    }

    public static void main(String[] args) throws IOException {
        run_stream(System.in);
    }

}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashSet;

public class D {

    static int log2(int i) {
        int ret=0;
        while(i>0) {
            ret++;
            i=i>>1;
        }
        return ret;
    }

    static void compute(int n, int[][] q) {
        //group queries by level
        int[] l2qcnt=new int[n+1];
        for (int i=0; i<q.length; i++) {
            if(q[i][0]==1) {
                l2qcnt[q[i][1]]++;
            }
        }
        int[][] l2q=new int[n+1][];
        for (int i=1; i<=n; i++) {
            l2q[i]=new int[l2qcnt[i]];
        }
        Arrays.fill(l2qcnt, 0);
        //end group queries by level

        HashSet<Integer> s=new HashSet<Integer>();
        for (int i=0; i<q.length; i++) {
            int lvl=q[i][1];
            if(q[i][0]==1) {
                l2q[lvl][l2qcnt[lvl]++]=i;
            } else {
                s.clear();
                int l=q[i][2], r=l;
                for (int j=lvl; j<=n; j++) {
                    for (int k=0; k<l2qcnt[j]; k++) {
                        int qidx=l2q[j][k];
                        int ql=q[qidx][2];
                        int qr=q[qidx][3];
                        if(!(r<ql||l>qr)) {
                            s.add(q[qidx][4]);
                        }
                    }
                    //update l,r
                    int extra=Integer.bitCount(r)==1? 1: 0;
                    l+=log2(l-1);
                    r+=log2(r-1);
                    r+=extra;
                }
                System.out.println(s.size());
            }
        }
    }

    static StringBuilder sb=new StringBuilder();
    static void parse(String l, int[] here) {
        sb.setLength(0);
        int len=l.length(), j=0;
        for (int i=0; i<len; i++) {
            char c=l.charAt(i);
            if(c==' ') {
                here[j++]=Integer.parseInt(sb.toString());
                sb.setLength(0);
            } else {
                sb.append(c);
            }
        }
        if(sb.length()>0) {
            here[j++]=Integer.parseInt(sb.toString());
        }
    }

    static void run_stream(InputStream ins) throws IOException {
        BufferedReader r=new BufferedReader(new InputStreamReader(System.in));
        String[] l=r.readLine().split(" ");
        int n=Integer.parseInt(l[0]);
        int m=Integer.parseInt(l[1]);

        int[][] q=new int[m][5];
        for (int i=0; i<m; i++) {
            parse(r.readLine(), q[i]);
            //q[i][1]--;
        }

        compute(n, q);
    }

    public static void main(String[] args) throws IOException {
        run_stream(System.in);
    }
}

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.InputMismatchException;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author pva10795
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		Scanner in = new Scanner(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Task solver = new Task();
		solver.solve(1, in, out);
		out.close();
	}
}

class Task {

    final int maxn = 1 << 17;

    public void solve(int testNumber, Scanner in, PrintWriter out) {
        /*int n = 7000;
        int a[] = new int[n];
        a[0] = 1;
        int sum = 1;
        for (int i = 0; i < n - 1; i++) {
            int cur = 1;
            a[i + 1] = a[i];
            while (cur <= a[i]) {
                cur *= 2;
                a[i + 1]++;
            }
            sum += a[i + 1];
        }
        for (int i = 0; i < 10; i++) System.out.println(a[i]);
        for (int i = 0; i < 10; i++) System.out.println(a[n - i - 1]);
        System.out.println(sum);*/
        int col[] = new int[1 << 20];
        int cur = 0;
        int L[] = new int[maxn], R[] = new int[maxn];
        for (int i = 1; i <= 110000; i++) {
            L[i] = ++cur;
            if ((i & (i - 1)) != 0) {
                R[i] = cur;
            } else R[i] = ++cur;
        }

        int n = in.nextInt();
        int m = in.nextInt();

        int l0[] = new int[n + 1], r0[] = new int[n + 1];

        int tp[] = new int[m], t[] = new int[m], l[] = new int[m], r[] = new int[m], x[] = new int[m];
        for (int i = 0; i < m; i++) {
            tp[i] = in.nextInt();
            if (tp[i] == 1) {
                t[i] = in.nextInt();
                l[i] = in.nextInt();
                r[i] = in.nextInt();
                x[i] = in.nextInt();
            } else {
                t[i] = in.nextInt();
                x[i] = in.nextInt();

                for (int o = 0; o < t[i]; o++) l0[o] = r0[o] = -1;
                l0[t[i]] = r0[t[i]] = x[i];
                int cL = x[i], cR = x[i];
                for (int o = t[i] + 1; o <= n; o++) {
                    cL = L[cL];
                    cR = R[cR];
                    l0[o] = cL;
                    r0[o] = cR;
                }

                int ans = 0;
                for (int j = 0; j < i; j++) if (tp[j] == 1) {
                    if (Math.min(r[j], r0[t[j]]) - Math.max(l[j], l0[t[j]]) >= 0) {
                        if (col[x[j]] != i + 1) {
                            ans++;
                            col[x[j]] = i + 1;
                        }
                    }
                }
                out.println(ans);
            }
        }
    }

}

class Scanner {
    BufferedReader in;
    StringTokenizer tok;

    public Scanner(InputStream in) {
        this.in = new BufferedReader(new InputStreamReader(in));
        tok = new StringTokenizer("");
    }

    private String tryReadNextLine() {
        try {
            return in.readLine();
        } catch (Exception e) {
            throw new InputMismatchException();
        }
    }

    public String nextToken() {
        while (!tok.hasMoreTokens()) {
            tok = new StringTokenizer(next());
        }
        return tok.nextToken();
    }

    public String next() {
        String newLine = tryReadNextLine();
        if (newLine == null)
            throw new InputMismatchException();
        return newLine;
    }

    public int nextInt() {
        return Integer.parseInt(nextToken());
    }

    }

//package codeforces;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class D {
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter writer = new PrintWriter(System.out);
    StringTokenizer stringTokenizer;

    String next() throws IOException {
        while (stringTokenizer == null || !stringTokenizer.hasMoreTokens()) {
            stringTokenizer = new StringTokenizer(reader.readLine());
        }
        return stringTokenizer.nextToken();
    }

    int nextInt() throws IOException {
        return Integer.parseInt(next());
    }

    long nextLong() throws IOException {
        return Long.parseLong(next());
    }

    final int MOD = 1000 * 1000 * 1000 + 7;
    int sum(int a, int b) {
        a += b;
        return a >= MOD ? a - MOD : a;
    }

    @SuppressWarnings("unchecked")
    void solve() throws IOException {
        int n = nextInt();
        int m = nextInt();
        final int LEVELS = 14;
        final int[][] parent = new int[LEVELS][1000 * 1000];
        int o = 0;
        for(int i = 1; o < parent[0].length - 1; i++) {
            parent[0][++o] = i;
            if(o < parent[0].length - 1 && (i & (i - 1)) == 0) {
                parent[0][++o] = i;
            }
        }
        for(int l = 1; l < LEVELS; l++) {
            for(int i = 1; i < parent[l].length; i++) {
                parent[l][i] = parent[l - 1][parent[l - 1][i]];
            }
        }
        class Utils {
            int get(int levelFrom, int levelTo, int x) {
                for(int i = 0; i < LEVELS; i++) {
                    if((levelFrom - levelTo >> i) % 2 == 1) {
                        x = parent[i][x];
                    }
                }
                return x;
            }
        }
        Utils utils = new Utils();
        int[] qLevel = new int[m];
        int[] qL = new int[m];
        int[] qR = new int[m];
        int[] qX = new int[m];
        int qC = 0;
        int[] set = new int[1 << 20];
        for(int i = 0; i < m; i++) {
            if(nextInt() == 1) {
                qLevel[qC] = nextInt();
                qL[qC] = nextInt();
                qR[qC] = nextInt();
                qX[qC] = nextInt();
                qC++;
            } else {
                int cnt = 0;
                int level = nextInt();
                int v = nextInt();
                for(int k = 0; k < qC; k++) {
                    if(level > qLevel[k]) {
                        continue;
                    }
                    int l = qL[k];
                    int r = qR[k];
                    for(int j = 0; j < LEVELS; j++) {
                        if(((qLevel[k] - level >> j) & 1) == 1) {
                            l = parent[j][l];
                            r = parent[j][r];
                        }
                    }
//                    int l = utils.get(qLevel[k], level, qL[k]);
//                    int r = utils.get(qLevel[k], level, qR[k]);
                    if(v >= l && v <= r) {
                        if(set[qX[k]] != i) {
                            set[qX[k]] = i;
                            cnt++;
                        }
                    }
                }
                writer.println(cnt);
            }
        }
        writer.close();
    }

    public static void main(String[] args) throws IOException {
        new D().solve();
    }
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.awt.Point;

public class Round223_Div2_D {
  static class Struct {
    int level, st, end, x;
    int idx;

    public Struct(int l, int s, int e, int xx) {
      level = l;
      st = s;
      end = e;
      x = xx;
    }
  }

  static class Triple{
    int level, pos,idx;
    public Triple(int l,int p,int i) {
      level=l;
      pos=p;
      idx=i;
    }
  }
  public static int highestOneBit(int x){
    int l=0, h=30,mid;
    while(l<h) {
      mid=l+((h-l)>>1);
      if((1l<<mid)> x) h=mid;
      else l=mid+1;
//      if((x|i) == x) {
//        res=idx;
//      }
//      idx++;
//      i<<=1;
    }
    return l;
  }

  public static void main(String[] args) throws Exception {
    PrintWriter out = new PrintWriter(System.out);
    int levelCnt = nextInt();
    int queryCnt = nextInt();
    TreeSet<Struct> structs = new TreeSet<>(new Comparator<Struct>() {
      @Override
      public int compare(Struct o1, Struct o2) {
        if(o1.level!=o2.level)
        return new Integer(o1.level).compareTo(o2.level);
        if (o1.st!=o2.st)
          return new Integer(o1.st).compareTo(o2.st);
        if (o1.end!=o2.end)
          return new Integer(o1.end).compareTo(o2.end);
        return new Integer(o1.x).compareTo(o2.x);
      }
    });
    Struct[] ar=new Struct[queryCnt+1];
    int[][] posit=new int[7001][2];
    int processIdx=0;
    int arIdx=0;
    for (int i = 0; i < queryCnt; i++) {
      int queryT = nextInt();
      if (queryT == 1) {
        ar[arIdx++]=(new Struct(nextInt(), nextInt(), nextInt(), nextInt()));
      } else {
        int level = nextInt();
        int pos = nextInt();
        HashSet<Integer> set = new HashSet<>();

        processIdx=level;
        posit[processIdx][0]=pos;
        posit[processIdx][1]=pos;
        for(int j=0;j<arIdx;j++) {
          Struct s=ar[j];
          if(s.level<level) continue;
          int st=posit[processIdx][0],end= posit[processIdx][1];
          while(processIdx < s.level) {
            int allbit=highestOneBit(end);
            int before=highestOneBit(st-1);
            int mine=allbit-before;
            int diff = end-st;

            st=st+before;
            end=st+diff+mine;
//            if(i==0){
//            System.out.println(st+" "+end+" shit "+(level+1)+" "+diff+" "+mine+" "+before+" "+Integer.highestOneBit(st-1));
//            }

            processIdx++;
            posit[processIdx][0]=st;
            posit[processIdx][1]=end;
          }
//          System.out.println(level+" "+st+" "+end+" a7a "+(i)+" ");
//          System.out.println("a7eh "+s.st+" "+s.end);
          if(!(posit[s.level][0]>s.end||posit[s.level][1]<s.st)) {
            set.add(s.x);
          }
        }
        out.println(set.size());
      }
    }
    out.flush();
  }

  static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  static StringTokenizer tokenizer = new StringTokenizer("");

  static int nextInt() throws Exception {
    return Integer.parseInt(next());
  }

  static double nextDouble() throws Exception {
    return Double.parseDouble(next());
  }

  static String next() throws Exception {
    while (true) {
      if (tokenizer.hasMoreTokens()) {
        return tokenizer.nextToken();
      }
      String s = br.readLine();
      if (s == null) {
        return null;
      }
      tokenizer = new StringTokenizer(s);
    }
  }
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

/**
 *
 * @author Don Li
 */
public class SerejaTree {

    int N = 7001;
    int M = (int) 1e6 + 5;

    Map<Integer, List<Segment>> map = new HashMap<>();

    void solve() {
        int[] num = new int[M];
        for (int i = 1; i < M; i++) {
            num[i] = Integer.numberOfTrailingZeros(Integer.highestOneBit(i)) + 1;
        }

        int n = in.nextInt(), m = in.nextInt();
        for (int i = 0; i < m; i++) {
            int type = in.nextInt();
            if (type == 1) {
                int t = in.nextInt(), l = in.nextInt(), r = in.nextInt(), x = in.nextInt();
                addSegment(t, l, r, x);
            } else {
                int t = in.nextInt(), v = in.nextInt();
                Set<Integer> set = new HashSet<>();
                for (int j = t, l = v, r = v; j <= n; j++) {
                    if (map.containsKey(j)) {
                        for (Segment seg : map.get(j)) {
                            if (!(seg.l > r || seg.r < l)) set.add(seg.x);
                        }
                    }
                    l = l + num[l - 1];
                    r = r + num[r];
                }
                out.println(set.size());
            }
        }
    }

    void addSegment(int t, int l, int r, int x) {
        if (!map.containsKey(t)) map.put(t, new ArrayList<>());
        map.get(t).add(new Segment(l, r, x));
    }

    static class Segment {
        int l, r, x;

        public Segment(int l, int r, int x) {
            this.l = l;
            this.r = r;
            this.x = x;
        }
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new SerejaTree().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(nextToken());
        }

        public long nextLong() {
            return Long.parseLong(nextToken());
        }

        public double nextDouble() {
            return Double.parseDouble(nextToken());
        }
    }
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

/**
 * @author Don Li
 */
public class SerejaTree {

    int N = 7001;
    int M = (int) 1e6 + 5;

    void solve() {
        int[] num = new int[M];
        for (int i = 1; i < M; i++) {
            num[i] = Integer.numberOfTrailingZeros(Integer.highestOneBit(i)) + 1;
        }

        int n = in.nextInt(), m = in.nextInt();
        List<Segment> segments = new ArrayList<>();
        int[] L = new int[N], R = new int[N];
        for (int i = 0; i < m; i++) {
            int type = in.nextInt();
            if (type == 1) {
                int t = in.nextInt(), l = in.nextInt(), r = in.nextInt(), x = in.nextInt();
                segments.add(new Segment(t, l, r, x));
            } else {
                int t = in.nextInt(), v = in.nextInt();
                L[t] = v;
                R[t] = v;
                for (int j = t + 1; j <= n; j++) {
                    L[j] = L[j - 1] + num[L[j - 1] - 1];
                    R[j] = R[j - 1] + num[R[j - 1]];
                }

                Set<Integer> set = new HashSet<>();
                for (Segment seg : segments) {
                    if (seg.t < t) continue;
                    if (L[seg.t] > seg.r || R[seg.t] < seg.l) continue;
                    set.add(seg.x);
                }
                out.println(set.size());
            }
        }
    }

    static class Segment {
        int t, l, r, x;

        public Segment(int t, int l, int r, int x) {
            this.t = t;
            this.l = l;
            this.r = r;
            this.x = x;
        }
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new SerejaTree().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(nextToken());
        }

        public long nextLong() {
            return Long.parseLong(nextToken());
        }

        public double nextDouble() {
            return Double.parseDouble(nextToken());
        }
    }
}

import java.util.TreeSet;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.Set;
import java.util.StringTokenizer;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskD solver = new TaskD();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskD {

    int[] t = new int[20];

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt(), m = in.nextInt();

        t[0] = 1;
        for (int i = 1; i < 20; i++) {
            t[i] = t[i - 1] * 2;
        }

        OP[] ops = new OP[m];
        for (int i = 0; i < m; i++) {
            OP op = new OP();
            ops[i] = op;
            op.type = in.nextInt();
            if (op.type == 1) {
                op.level = in.nextInt();
                op.left = in.nextInt();
                op.right = in.nextInt();
                op.element = in.nextInt();
            } else {
                op.level = in.nextInt();
                op.pos = in.nextInt();
                op.set = new TreeSet<>();
            }
        }

        int[] ll = new int[n + 1];
        int[] lr = new int[n + 1];

        for (int i = m - 1; i >= 0; i--) {
            OP o = ops[i];
            if (o.type == 1) {
                buildPath(ll, o.level, o.left);
                buildPath(lr, o.level, o.right);
                for (int h = i + 1; h < m; h++) {
                    if (ops[h].type == 2 && ops[h].level <= o.level) {
                        OP oo = ops[h];
                        if (ll[oo.level] <= oo.pos && oo.pos <= lr[oo.level]) {
                            oo.set.add(o.element);
                        }
                    }
                }
            }
        }

        for (int i = 0; i < m; i++) {
            if (ops[i].type == 2) {
                out.println(ops[i].set.size());
            }
        }

    }

    void buildPath(int[] levels, int level, int pos) {
        levels[level] = pos;

        for (int l = level - 1; l >= 1; l--) {
            int i = 0;
            int curp = 0, ans = 0;
            pos = levels[l + 1];

            while (true) {
                if (curp + 2 >= pos) {
                    ans = t[i];
                    break;
                } else if (curp + 2 + t[i + 1] - t[i] - 1 >= pos) {
                    ans = t[i] + (pos - curp - 2);
                    break;
                }
                curp += 2 + t[i + 1] - t[i] - 1;
                i++;
            }

            levels[l] = ans;
        }
    }

    public static class OP {
        int type;
        int left, right;
        int element;

        int level, pos;
        Set<Integer> set;
    }

}

class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream), 32768);
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

}

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Scanner;

public class D {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        LinkedList<Interval> L[] = new LinkedList[n];
        for (int i = 0; i < n; i++)
            L[i] = new LinkedList<Interval>();
        int max = 2000000;
        int[] C = new int[max];
        for (int i = 1; i < max; i++)
            C[i] = C[i - 1] + ((i & (i - 1)) == 0 ? 2 : 1);
        HashSet<Integer> res = new HashSet<Integer>();
        for (int i = 0; i < m; i++) {
            int c = in.nextInt();
            int t = in.nextInt() - 1;
            if (c == 1) {
                int l = in.nextInt();
                int r = in.nextInt();
                int x = in.nextInt();
                L[t].add(new Interval(l, r, x));
            } else {
                int v = in.nextInt();
                int st = v;
                int end = v;
                res.clear();
                for (int j = t; j < n; j++) {
                    for (Interval p : L[j])
                        if ((p.l <= end && st <= p.r))
                            res.add(p.x);
                    st = C[st - 1] + 1;
                    end = C[end];
                }
                System.out.println(res.size());
            }
        }
    }
}

class Interval {
    int l, r, x;

    public Interval(int i, int j, int k) {
        l = i;
        r = j;
        x = k;
    }
}

import java.io.*;
import java.util.*;

public class B {
    public static void main(String[] args) throws Exception {
        new B().solve();
        // new FileInputStream(new File("input.txt")),
        // new PrintStream(new FileOutputStream(new File("output.txt"))));
    }

    void solve() throws IOException {
        BufferedReader in = new BufferedReader(new
                InputStreamReader(System.in));
        Scanner sc = new Scanner(System.in);
        String[] sp;

        // n, m
        sp = in.readLine().split(" ");
        int n = Integer.parseInt(sp[0]);
        int m = Integer.parseInt(sp[1]);

        // child
        int[] childL = new int[140000];
        int[] childR = new int[140000];
        {
            int ci = 1;
            for (int i = 1; i < childL.length; i++) {
                childL[i] = childR[i] = ci++;
                if ((i & -i) == i) {// 2^k
                    childR[i] = ci++;
                }
            }
        }

        int size = 0;
        int[] level = new int[m];
        int[] left = new int[m];
        int[] right = new int[m];
        int[] x = new int[m];
        HashSet<Integer> set = new HashSet<Integer>();
        StringBuilder sb = new StringBuilder();
        int[] sortedIdx = new int[m];

        // operations
        for (int i = 0; i < m; i++) {
            sp = in.readLine().split(" ");
            int op = Integer.parseInt(sp[0]);
            if (op == 1) {
                level[size] = Integer.parseInt(sp[1]);
                left[size] = Integer.parseInt(sp[2]);
                right[size] = Integer.parseInt(sp[3]);
                x[size] = Integer.parseInt(sp[4]);
                int idx = size;
                while (idx > 0 && level[sortedIdx[idx - 1]] > level[size]) {
                    sortedIdx[idx] = sortedIdx[idx - 1];
                    idx--;
                }
                sortedIdx[idx] = size;
                size++;

            } else {// 2
                int lv2 = Integer.parseInt(sp[1]);
                int l, r;
                l = r = Integer.parseInt(sp[2]);

                set.clear();

                for (int _jj = 0; _jj < size; _jj++) {
                    int k = sortedIdx[_jj];
                    if (level[k] < lv2) {
                        continue;
                    }
                    while (lv2 < level[k]) {
                        l = childL[l];
                        r = childR[r];
                        lv2++;
                    }
                    if (l <= right[k] && left[k] <= r) {
                        // ok
                        set.add(x[k]);
                    }
                }
                sb.append(set.size() + "\n");
            }
        }
        System.out.print(sb);
    }
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//

import java.io.*;
import java.util.*;

public class B {
    public static void main(String[] args) throws Exception {
        new B().solve();
        // new FileInputStream(new File("input.txt")),
        // new PrintStream(new FileOutputStream(new File("output.txt"))));
    }

    void solve() throws IOException {
        BufferedReader in = new BufferedReader(new
                InputStreamReader(System.in));
        Scanner sc = new Scanner(System.in);
        String[] sp;

        // n, m
        sp = in.readLine().split(" ");
        int n = Integer.parseInt(sp[0]);
        int m = Integer.parseInt(sp[1]);

        // par
        par2 = new int[15][140000];
        {
            // 1
            int nci = 1;
            for (int pos = 1; nci < par2[0].length; pos++) {
                if ((pos & -pos) == pos) {// 2^k
                    par2[0][nci++] = pos;
                    par2[0][nci++] = pos;
                } else {
                    par2[0][nci++] = pos;
                }
            }
            // 2~
            for (int lv2 = 1; lv2 < par2.length; lv2++) {
                for (int pos = 1; pos < par2[0].length; pos++) {
                    par2[lv2][pos] = par2[lv2 - 1][par2[lv2 - 1][pos]];
                }
            }
        }

        int size = 0;
        int[] level = new int[m];
        int[] left = new int[m];
        int[] right = new int[m];
        int[] x = new int[m];
        int[] flg = new int[2000000];
        StringBuilder sb = new StringBuilder();

        // operations
        for (int i = 0; i < m; i++) {
            sp = in.readLine().split(" ");
            int op = Integer.parseInt(sp[0]);
            if (op == 1) {
                level[size] = Integer.parseInt(sp[1]);
                left[size] = Integer.parseInt(sp[2]);
                right[size] = Integer.parseInt(sp[3]);
                x[size] = Integer.parseInt(sp[4]);
                size++;
            } else {// 2
                int lv2 = Integer.parseInt(sp[1]);
                int p = Integer.parseInt(sp[2]);
                int count = 0;

                for (int ai = 0; ai < size; ai++) {
                    int lv1 = level[ai];
                    if (lv2 <= lv1) {
                        int l = par(lv1 - lv2, left[ai]);
                        int r = par(lv1 - lv2, right[ai]);
                        if (l <= p && p <= r && flg[x[ai]] != i) {
                            flg[x[ai]] = i;
                            count++;
                        }
                    }
                }
                sb.append(count + "\n");
            }
        }
        System.out.print(sb);
    }
    int[][] par2;
    int par(int lv, int pos) {
        for (int b = 0; (lv >> b) > 0; b++) {
            if ((lv >> b & 1) == 1) {
                pos = par2[b][pos];
            }
        }
        return pos;
    }
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//

import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskB solver = new TaskB();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskB {
    static final int MAXX = (int) 1.1e6;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt();
        int m = in.nextInt();
        int[] cnt = new int[n + 1];
        int[] left = new int[]{0};
        int[] right = new int[]{0};
        cnt[1] = 1;
        for (int level = 1; level < n; level = level + 1){
            left = Arrays.copyOf(left, cnt[level] + 1);
            right = Arrays.copyOf(right, cnt[level] + 1);
            cnt[level + 1] = cnt[level];
            if (level == 1) cnt[level + 1] = 0;
            for (int position = cnt[level - 1] + 1; position <= cnt[level]; position = position + 1){
                if ((position & (position - 1)) == 0) {
                    left[position] = cnt[level + 1] + 1;
                    right[position] = cnt[level + 1] + 2;
                    cnt[level + 1] = cnt[level + 1] + 2;
                }else{
                    left[position] = right[position] = cnt[level + 1] + 1;
                    cnt[level + 1] = cnt[level + 1] + 1;
                }
            }
        }
        int generation = 0;
        int[] lastgen = new int[MAXX];
        int[] t = new int[m];
        int[] l = new int[m];
        int[] r = new int[m];
        int[] x = new int[m];
        int[] firstbyt = new int[n + 1];
        Arrays.fill(firstbyt, -1);
        int[] nextsamet = new int[m];
        int type1 = 0;
        for (int i = 0; i < m; ++i) {
            int ct = in.nextInt();
            if (ct == 1) {
                t[type1] = in.nextInt();
                l[type1] = in.nextInt();
                r[type1] = in.nextInt();
                x[type1] = in.nextInt();
                nextsamet[type1] = firstbyt[t[type1]];
                firstbyt[t[type1]] = type1;
                ++type1;
            } else {
                int qt = in.nextInt();
                int ql = in.nextInt();
                int qr = ql;
                ++generation;
                int res = 0;
                while (qt <= n) {
                    int cur = firstbyt[qt];
                    while (cur >= 0) {
                        if (r[cur] < ql || l[cur] > qr) {
                        } else {
                            if (lastgen[x[cur]] < generation) {
                                lastgen[x[cur]] = generation;
                                ++res;
                            }
                        }
                        cur = nextsamet[cur];
                    }
                    if (qt < n) {
                        ql = left[ql];
                        qr = right[qr];
                    }
                    ++qt;
                }
                out.println(res);
            }
        }
    }
}

class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    }

import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Stack;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Queue;

public class Main {
    class node{
        int t,l,r,x;
        node(){}
        node(int tt,int l,int r,int xx){
            this.t=tt;
            this.l=(int)l;
            this.r=(int)r;
            this.x=xx;
        }
    };
    node[] q = new node[10000];
    int tail;
    int[] L = new int[10000], R = new int[10000];
    int cal(int x){
        int cnt=x,now=1;
        while(now<=x){
            cnt++;
            now*=2;
        }
        return cnt;
    }
    int n, m;
    TreeSet<Integer> st = new TreeSet();
    void work() {
        n = cin.nextInt();
        m = cin.nextInt();
        tail = 0;
        for(int i = 0; i < 10000; i++)L[i] = R[i] = 0;
        for(int i=0;i<m;++i)
        {
            int ty,t,x;
            int l,r,v;
            ty = cin.nextInt();
            if(ty==1){
                t = cin.nextInt(); l = cin.nextInt(); r = cin.nextInt();
                x = cin.nextInt();
                q[tail++] = new node(t,l,r,x);
            }else
            {
                t = cin.nextInt(); v = cin.nextInt();
                L[t]=v;R[t]=v;
                for(int i1=t+1;i1<=n;++i1){
                    L[i1]=cal(L[i1-1]-1)+1;
                    R[i1]=cal(R[i1-1]);
                }
                st.clear();

                for(int j=0;j<tail;++j){
                    if(q[j].t<t)continue;
                    if(q[j].r<L[q[j].t]||q[j].l>R[q[j].t])continue;
                    st.add(q[j].x);
                }
                out.println(st.size());
            }
        }
    }

    Main() {
        cin = new Scanner(System.in);
        out = new PrintWriter(System.out);
    }

    public static void main(String[] args) {
        Main e = new Main();
        e.work();
        out.close();
    }

    public Scanner cin;
    public static PrintWriter out;
    static int N = 3005;
    static int M = 20005;
    DecimalFormat df=new DecimalFormat("0.0000");
    static int inf = (int) 1e9 + 7;
    static long inf64 = (long) 1e18*2;
    static double eps = 1e-8;
    static double Pi = Math.PI;
    static int mod = 1000000007 ;
/*
    class Edge{
        int from, to, nex;
        Edge(){}
        Edge(int from, int to, int nex){
            this.from = from;
            this.to = to;
            this.nex = nex;
        }
    }
    Edge[] edge = new Edge[M<<1];
    int[] head = new int[N];
    int edgenum;
    void init_edge(){for(int i = 0; i < N; i++)head[i] = -1; edgenum = 0;}
    void add(int u, int v){
        edge[edgenum] = new Edge(u, v, head[u]);
        head[u] = edgenum++;
    }/*
    int upper_bound(int[] A, int l, int r, int val) {// upper_bound(A+l,A+r,val)-A;
        int pos = r;
        r--;
        while (l <= r) {
            int mid = (l + r) >> 1;
            if (A[mid] <= val) {
                l = mid + 1;
            } else {
                pos = mid;
                r = mid - 1;
            }
        }
        return pos;
    }/**/

    int Pow(int x, int y) {
        int ans = 1;
        while (y > 0) {
            if ((y & 1) > 0)
                ans *= x;
            y >>= 1;
            x = x * x;
        }
        return ans;
    }
    double Pow(double x, int y) {
        double ans = 1;
        while (y > 0) {
            if ((y & 1) > 0)
                ans *= x;
            y >>= 1;
            x = x * x;
        }
        return ans;
    }
    int Pow_Mod(int x, int y, int mod) {
        int ans = 1;
        while (y > 0) {
            if ((y & 1) > 0)
                ans *= x;
            ans %= mod;
            y >>= 1;
            x = x * x;
            x %= mod;
        }
        return ans;
    }
    long Pow(long x, long y) {
        long ans = 1;
        while (y > 0) {
            if ((y & 1) > 0)
                ans *= x;
            y >>= 1;
            x = x * x;
        }
        return ans;
    }
    long Pow_Mod(long x, long y, long mod) {
        long ans = 1;
        while (y > 0) {
            if ((y & 1) > 0)
                ans *= x;
            ans %= mod;
            y >>= 1;
            x = x * x;
            x %= mod;
        }
        return ans;
    }

    int gcd(int x, int y){
        if(x>y){int tmp = x; x = y; y = tmp;}
        while(x>0){
            y %= x;
            int tmp = x; x = y; y = tmp;
        }
        return y;
    }
    int max(int x, int y) {
        return x > y ? x : y;
    }

    int min(int x, int y) {
        return x < y ? x : y;
    }

    double max(double x, double y) {
        return x > y ? x : y;
    }

    double min(double x, double y) {
        return x < y ? x : y;
    }

    long max(long x, long y) {
        return x > y ? x : y;
    }

    long min(long x, long y) {
        return x < y ? x : y;
    }

    int abs(int x) {
        return x > 0 ? x : -x;
    }

    double abs(double x) {
        return x > 0 ? x : -x;
    }

    long abs(long x) {
        return x > 0 ? x : -x;
    }

    boolean zero(double x) {
        return abs(x) < eps;
    }
    double sin(double x){return Math.sin(x);}
    double cos(double x){return Math.cos(x);}
    double tan(double x){return Math.tan(x);}
    double sqrt(double x){return Math.sqrt(x);}
}

import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Random;
import java.io.Writer;
import java.util.List;
import java.io.IOException;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.math.BigInteger;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Árysson Cavalcanti
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        TaskB solver = new TaskB();
        solver.solve(1, in, out);
        out.close();
    }
}

class TaskB {
    public void solve(int testNumber, InputReader in, OutputWriter out) {
        int n=in.readInt(), m=in.readInt();
        List<Pair<IntPair, IntPair>> list=new ArrayList<>();
        while (m-->0) {
            int type=in.readInt();
            if (type==1) {
                int t=in.readInt(), l=in.readInt(), r=in.readInt(), x=in.readInt();
                list.add(Pair.makePair(new IntPair(t, l), new IntPair(r, x)));
            } else {
                int t=in.readInt(), v=in.readInt();
                IntCollection set=new IntHashSet();
                int[] from=new int[n+1], to=new int[n+1];
                for (int i=1; i<t; i++) {
                    from[i]=v+1;
                    to[i]=v;
                }
                from[t]=to[t]=v;
                for (int i=t+1; i<=n; i++) {
                    from[i]=from[i-1]+Integer.numberOfTrailingZeros(Integer.highestOneBit(from[i-1]))+((from[i-1]&(from[i-1]-1))==0?0:1);
                    to[i]=to[i-1]+Integer.numberOfTrailingZeros(Integer.highestOneBit(to[i-1]))+1;
                }
                for (Pair<IntPair, IntPair> i: list) {
                    int l=i.first.second, r=i.second.first, x=i.second.second;
                    t=i.first.first;
                    if (r>=from[t] && l<=to[t] && from[t]<=to[t]) {
                        set.add(x);
                        //out.printLine(t, l, r, x, from[t], to[t]);
                    }
                }
                //out.printLine(from);
                //out.printLine(to);
                out.printLine(set.size());
            }
        }
    }
}

class InputReader {

    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;
    private SpaceCharFilter filter;

    public InputReader(InputStream stream) {
        this.stream = stream;
    }

    public int read() {
        if (numChars == -1)
            throw new InputMismatchException();
        if (curChar >= numChars) {
            curChar = 0;
            try {
                numChars = stream.read(buf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (numChars <= 0)
                return -1;
        }
        return buf[curChar++];
    }

    public int readInt() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        int res = 0;
        do {
            if (c < '0' || c > '9')
                throw new InputMismatchException();
            res *= 10;
            res += c - '0';
            c = read();
        } while (!isSpaceChar(c));
        return res * sgn;
    }

    public boolean isSpaceChar(int c) {
        if (filter != null)
            return filter.isSpaceChar(c);
        return isWhitespace(c);
    }

    public static boolean isWhitespace(int c) {
        return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public interface SpaceCharFilter {
        public boolean isSpaceChar(int ch);
    }
}

class OutputWriter {
    private final PrintWriter writer;

    public OutputWriter(OutputStream outputStream) {
        writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }

    public void close() {
        writer.close();
    }

    public void printLine(int i) {
        writer.println(i);
    }
}

class Pair<U, V> implements Comparable<Pair<U, V>> {
    public final U first;
    public final V second;

    public static<U, V> Pair<U, V> makePair(U first, V second) {
        return new Pair<U, V>(first, second);
    }

    private Pair(U first, V second) {
        this.first = first;
        this.second = second;
    }

    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Pair pair = (Pair) o;

        return !(first != null ? !first.equals(pair.first) : pair.first != null) && !(second != null ? !second.equals(pair.second) : pair.second != null);

    }

    public int hashCode() {
        int result = first != null ? first.hashCode() : 0;
        result = 31 * result + (second != null ? second.hashCode() : 0);
        return result;
    }

    public String toString() {
        return "(" + first + "," + second + ")";
    }

    public int compareTo(Pair<U, V> o) {
        int value = ((Comparable<U>)first).compareTo(o.first);
        if (value != 0)
            return value;
        return ((Comparable<V>)second).compareTo(o.second);
    }
}

class IntPair implements Comparable<IntPair> {
    public final int first, second;

    public IntPair(int first, int second) {
        this.first = first;
        this.second = second;
    }

    public String toString() {
        return "(" + first + "," + second + ")";
    }

    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        IntPair intPair = (IntPair) o;

        return first == intPair.first && second == intPair.second;

    }

    public int hashCode() {
        int result = first;
        result = 31 * result + second;
        return result;
    }

    public int compareTo(IntPair o) {
        if (first < o.first)
            return -1;
        if (first > o.first)
            return 1;
        if (second < o.second)
            return -1;
        if (second > o.second)
            return 1;
        return 0;
    }
}

abstract class IntCollection {
    public abstract int size();
    public abstract void add(int value);

}

class IntHashSet extends IntSet {
    private static final Random RND = new Random();
    private static final int[] SHIFTS = new int[4];
    private static final byte PRESENT_MASK = 1;

    static {
        for (int i = 0; i < 4; i++)
            SHIFTS[i] = RND.nextInt(31) + 1;
    }

    private int size;
    private int realSize;
    private int[] values;
    private byte[] present;
    private int step;
    private int ratio;

    public IntHashSet() {
        this(3);
    }

    public IntHashSet(int capacity) {
        capacity = Math.max(capacity, 1);
        values = new int[capacity];
        present = new byte[capacity];
        ratio = 2;
        initStep(capacity);
    }

    private void initStep(int capacity) {
        step = RND.nextInt(capacity - 2) + 1;
        while (IntegerUtils.gcd(step, capacity) != 1)
            step++;
    }

    public int size() {
        return size;
    }

    public void add(int value) {
        ensureCapacity((realSize + 1) * ratio + 2);
        int current = getHash(value);
        while (present[current] != 0) {
            if ((present[current] & PRESENT_MASK) != 0 && values[current] == value) {
                return;
            }
            current += step;
            if (current >= values.length)
                current -= values.length;
        }
        while ((present[current] & PRESENT_MASK) != 0) {
            current += step;
            if (current >= values.length)
                current -= values.length;
        }
        if (present[current] == 0) {
            realSize++;
        }
        present[current] = PRESENT_MASK;
        values[current] = value;
        size++;
    }

    private int getHash(int value) {
        int result = value;
        for (int i : SHIFTS)
            result ^= value >> i;
        result %= values.length;
        if (result < 0)
            result += values.length;
        return result;
    }

    private void ensureCapacity(int capacity) {
        if (values.length < capacity) {
            capacity = Math.max(capacity * 2, values.length);
            rebuild(capacity);
        }
    }

    private void rebuild(int capacity) {
        initStep(capacity);
        int[] oldValues = values;
        byte[] oldPresent = present;
        values = new int[capacity];
        present = new byte[capacity];
        size = 0;
        realSize = 0;
        for (int i = 0; i < oldValues.length; i++) {
            if ((oldPresent[i] & PRESENT_MASK) == PRESENT_MASK)
                add(oldValues[i]);
        }
    }

}

abstract class IntSet extends IntCollection {
}

class IntegerUtils {

    public static int gcd(int a, int b) {
        a = Math.abs(a);
        b = Math.abs(b);
        while (b != 0) {
            int temp = a % b;
            a = b;
            b = temp;
        }
        return a;
    }

}

import java.io.*;
import java.util.*;
import java.lang.reflect.*;

public class Main {

	static long CURRENT_TIME_NANO = System.nanoTime();
	static int[] cnt2;
	static int k = 1000000;
	static int[][] nextnum;
	static int maxl = 14;

	static int under(int l1, int pos, int l2) {
		for (int i = maxl - 1; i >= 0; i--)
			if (l2 >= (1 << i)) {
				pos = nextnum[i][pos];
				l2 -= 1 << i;
			}
		return pos;
	}

	public static void main(String[] args) throws Exception {

		cnt2 = new int[k + 1];
		cnt2[1] = 0;
		for (int i = 0; i < 20; i++) {
			for (int j = (1 << i) + 1; j <= (1 << (i + 1)) && j < k; j++) cnt2[j] = i + 1;
		}

		nextnum = new int[maxl][k + 1];
		for (int i = 1; i <= k; i++)
			if (i + cnt2[i] < k) nextnum[0][i] = i + cnt2[i];
			else nextnum[0][i] = k;

		for (int i = 0; i < maxl - 1; i++)
			for (int j = 1; j <= k; j++) nextnum[i + 1][j] = nextnum[i][nextnum[i][j]];

		int n = next();
		int m = next();

		int[][] op = new int[m][4];
		int index = 0;

		for (int i = 0; i < m; i++) {
			int type = next();
			if (type == 1) op[index++] = new int[] {next(), next(), next(), next()};
			else {
				int l = next();
				int pos = next();
				HashSet<Integer> set = new HashSet<Integer>();

				for (int j = 0; j < index; j++) {
					int[] opp = op[j];
					if (opp[0] < l) continue;
					int left = under(l, pos, opp[0] - l);
					int right = under(l, pos + 1, opp[0] - l);
//					sout("---> " + l + " " + pos + " " + opp[0] + " " + left + " " + right);
					if (left > opp[2]) continue;
					if (right <= opp[1]) continue;
					set.add(opp[3]);
				}

				out.println(set.size());
			}
		}

		out.close();
	}

	static void printtime() {System.out.println((System.nanoTime() - CURRENT_TIME_NANO)*1e-9);}
	static void nexttime() {printtime(); CURRENT_TIME_NANO = System.nanoTime();}
	static PrintWriter out = new PrintWriter(System.out);

	static BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(System.in));
	static StringTokenizer in = new StringTokenizer("");

	static String nextToken() throws Exception {
		if (!in.hasMoreTokens()) in = new StringTokenizer(bufferedreader.readLine());
		return in.nextToken();
	}

	static int next()  throws Exception {return Integer.parseInt(nextToken());};
	static int[] next(int n) throws Exception {
		int[] x = new int[n];
		for (int i = 0; i < n; i++) x[i] = next();
		return x;
	}
	static int[][] next(int n, int m) throws Exception {
		int[][] x = new int[n][];
		for (int i = 0; i < n; i++) x[i] = next(m);
		return x;
	}

	static long nextl() throws Exception {return Long.parseLong(nextToken());};
	static long[] nextl(int n) throws Exception {
		long[] x = new long[n];
		for (int i = 0; i < n; i++) x[i] = nextl();
		return x;
	}
	static long[][] nextl(int n, int m) throws Exception {
		long[][] x = new long[n][];
		for (int i = 0; i < n; i++) x[i] = nextl(m);
		return x;
	}

	static double nextd() throws Exception {return Double.parseDouble(nextToken());};
	static double[] nextd(int n) throws Exception {
		double[] x = new double[n];
		for (int i = 0; i < n; i++) x[i] = nextd();
		return x;
	}
	static double[][] nextd(int n, int m) throws Exception {
		double[][] x = new double[n][];
		for (int i = 0; i < n; i++) x[i] = nextd(m);
		return x;
	}

	static String nextline() throws Exception {
		in = new StringTokenizer("");
		return bufferedreader.readLine();
	}

	static void sout(String s) {System.out.println(s);}
	static void sout(long x) {System.out.println(x);}
	static void sout(int[] x) {for (int xx : x) System.out.print(xx + " "); System.out.println();}
	static void sout(long[] x) {for (long xx : x) System.out.print(xx + " "); System.out.println();}
	static void sout(int[][] x) {for (int[] xx : x) sout(xx); System.out.println();}
	static void sout(long[][] x) {for (long[] xx : x) sout(xx); System.out.println();}

}

import java.util.*;
import java.io.*;
import java.math.*;

import static java.lang.Math.*;

public class Solution implements Runnable {

	static final int MAX_CNT = 109315;

	public void solve() throws Exception {
		boolean isPowTwo [] = new boolean [MAX_CNT + 1];
		for (int h = 1; h <= MAX_CNT; h *= 2)
			isPowTwo[h] = true;

		int n = sc.nextInt();
		int m = sc.nextInt();

		int p[][] = new int [14][MAX_CNT + 1];
		int prev[] = new int [MAX_CNT + 1];
		int q[] = new int [MAX_CNT + 1];
		q[0] = 1;
		prev[1] = 1;
		int head = 0;
		int tail = 1;

		while (head < tail) {
			int v = q[head++];
			p[0][v] = prev[v];
			for (int i = 1; i <= 13; i++) {
				p[i][v] = p[i - 1][p[i - 1][v]];
			}
			if (tail + 1 <= MAX_CNT) {
				prev[tail + 1] = v;
				q[tail++] = tail;
				if (isPowTwo[v] && tail + 1 <= MAX_CNT) {
					prev[tail + 1] = v;
					q[tail++] = tail;
				}
			}
		}

		int type [] = new int [m];
		int lvl [] = new int [m];
		int l [] = new int [m];
		int r [] = new int [m];
		int x [] = new int [m];

		int exists [] = new int [1000000 + 1];
		Arrays.fill(exists, -1);

		for (int i = 0; i < m; i++) {
			type[i] = sc.nextInt();
			if (type[i] == 1) {
				lvl[i] = sc.nextInt();
				l[i] = sc.nextInt();
				r[i] = sc.nextInt();
				x[i] = sc.nextInt();
			} else {
				int level = sc.nextInt();
				int pos = sc.nextInt();
				int answer = 0;
				for (int j = 0; j < i; j++) {
					if (type[j] == 1 && lvl[j] >= level) {
						int pl = l[j];
						int pr = r[j];
						int dst = lvl[j] - level;
						for (int k = 13; k >= 0 && dst > 0; k--) {
							if ((1 << k) <= dst) {
								dst -= (1 << k);
								pl = p[k][pl];
								pr = p[k][pr];
							}
						}
						if (pl <= pos && pr >= pos && exists[x[j]] != i) {
							exists[x[j]] = i;
							answer++;
						}
					}
				}
				out.println(answer);
			}
		}
	}

	static Throwable t;

	BufferedReader in;
	FastScanner sc;
	PrintWriter out;

	@Override
	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			sc = new FastScanner(in);
			solve();
		} catch (Throwable t) {
			Solution.t = t;
		} finally {
			out.close();
		}
	}

	public static void main(String[] args) throws Throwable {
		Thread thread = new Thread(null, new Solution(), "", 1 << 26);
		thread.start();
		thread.join();
		if (Solution.t != null)
			throw t;
	}

}

class FastScanner {

	BufferedReader in;
	StringTokenizer st;

	public FastScanner(BufferedReader in) {
		this.in = in;
	}

	public String nextToken() throws Exception {
		while (st == null || !st.hasMoreTokens())
			st = new StringTokenizer(in.readLine());
		return st.nextToken();
	}

	public int nextInt() throws Exception {
		return Integer.parseInt(nextToken());
	}

	public long nextLong() throws Exception {
		return Long.parseLong(nextToken());
	}

	public double nextDouble() throws Exception {
		return Double.parseDouble(nextToken());
	}

}

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.InputMismatchException;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class B {

	static PrintWriter out;
	static InputReader in;
	static BigInteger[] pow = new BigInteger[7001];
	public static void main(String[] args) throws Exception {
		in = new InputReader(System.in);
		out = new PrintWriter(System.out);

		pow[0] = BigInteger.ONE;
		for(int i=1;i<=7000;i++) {
			pow[i] = pow[i-1] .multiply(BigInteger.valueOf(2));
		}

		int N = in.nextInt();
		int M = in.nextInt();

		BigInteger[][] queries = new BigInteger[M][5];
		Set<Node> nodes = new HashSet();
		Map<Node, Set<Integer>> nodeToSet = new HashMap();
		for(int qi=0; qi<M;qi++) {
			int type = in.nextInt();
			if(type == 1) {
				queries[qi][0] = v(1);
				queries[qi][1] = new BigInteger(in.nextToken());
				queries[qi][2] = new BigInteger(in.nextToken());
				queries[qi][2] = queries[qi][2].subtract(BigInteger.ONE);
				queries[qi][3] = new BigInteger(in.nextToken());
				queries[qi][3] = queries[qi][3].subtract(BigInteger.ONE);
				queries[qi][4] = new BigInteger(in.nextToken());
			} else {
				queries[qi][0] = v(2);
				queries[qi][1] = new BigInteger(in.nextToken());
				queries[qi][2] = new BigInteger(in.nextToken());
				queries[qi][2] = queries[qi][2].subtract(BigInteger.ONE);
				Node n = new Node((int)queries[qi][1].longValue(), queries[qi][2]);
				nodes.add(n);
				nodeToSet.put(n, new HashSet());
			}
		}

		for(int qi=0; qi<M;qi++) {
			if(queries[qi][0].longValue() == 1) {
				int val = (int) queries[qi][4].longValue();
				for(Node n : nodes) {
					int level = (int) queries[qi][1].longValue();
					BigInteger l = queries[qi][2];
					BigInteger r = queries[qi][3];
					boolean isparent = false;

					if(n.level <= level) {
						BigInteger cl = convert(l, level, n.level);
						BigInteger cr = convert(r, level, n.level);
						isparent = n.pos.compareTo(cl) >= 0 && n.pos.compareTo(cr) <= 0;
					}

					if(isparent) {
						nodeToSet.get(n).add(val);
					}
				}
			} else {
				Node n = new Node((int)queries[qi][1].longValue(), queries[qi][2]);
				out.println(nodeToSet.get(n).size());
			}
		}
		out.close();
	}

	static BigInteger convert(BigInteger pos, int slevel, int tlevel) {
		return pos.divide(pow[slevel-tlevel]);
	}

	static class Node {
		public int level;
		public BigInteger pos;
		public Node(int level, BigInteger pos) {
			this.level = level;
			this.pos = pos;
		}
		@Override
		public String toString() {
			return "Node [level=" + level + ", pos=" + pos + "]";
		}
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + level;
			result = prime * result + ((pos == null) ? 0 : pos.hashCode());
			return result;
		}
		@Override
		public boolean equals(Object obj) {
			Node other = (Node) obj;
			if (level != other.level)
				return false;
			if (pos == null) {
				if (other.pos != null)
					return false;
			} else if (!pos.equals(other.pos))
				return false;
			return true;
		}
	}

	static BigInteger v(long x){
		return BigInteger.valueOf(x);
	}

	static class InputReader {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;
		private SpaceCharFilter filter;

		public InputReader(InputStream stream) {
			this.stream = stream;
		}

		public int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		public int nextInt() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-') {
				sgn = -1;
				c = read();
			}
			int res = 0;
			do {
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			return res * sgn;
		}

		public long nextLong() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-') {
				sgn = -1;
				c = read();
			}
			long res = 0;
			do {
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			return res * sgn;
		}

		public String nextToken() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public boolean isSpaceChar(int c) {
			if (filter != null)
				return filter.isSpaceChar(c);
			return isWhitespace(c);
		}

		public static boolean isWhitespace(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		public interface SpaceCharFilter {
			public boolean isSpaceChar(int ch);
		}
	}
}

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.InputMismatchException;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class B {

	static PrintWriter out;
	static InputReader in;
	static BigInteger[] pow = new BigInteger[7001];
	public static void main(String[] args) throws Exception {
		in = new InputReader(System.in);
		out = new PrintWriter(System.out);

		pow[0] = BigInteger.ONE;
		for(int i=1;i<=7000;i++) {
			pow[i] = pow[i-1] .multiply(BigInteger.valueOf(2));
		}

		int N = in.nextInt();
		int M = in.nextInt();

		BigInteger[][] queries = new BigInteger[M][5];
		List<Node> nodes = new ArrayList();
		Map<Node, Set<Integer>> nodeToSet = new HashMap();
		for(int qi=0; qi<M;qi++) {
			int type = in.nextInt();
			if(type == 1) {
				queries[qi][0] = v(1);
				queries[qi][1] = new BigInteger(in.nextToken());
				queries[qi][2] = new BigInteger(in.nextToken());
				queries[qi][2] = queries[qi][2].subtract(BigInteger.ONE);
				queries[qi][3] = new BigInteger(in.nextToken());
				queries[qi][3] = queries[qi][3].subtract(BigInteger.ONE);
				queries[qi][4] = new BigInteger(in.nextToken());
			} else {
				queries[qi][0] = v(2);
				queries[qi][1] = new BigInteger(in.nextToken());
				queries[qi][2] = new BigInteger(in.nextToken());
				queries[qi][2] = queries[qi][2].subtract(BigInteger.ONE);
				Node n = new Node((int)queries[qi][1].longValue(), queries[qi][2]);
				nodes.add(n);
				nodeToSet.put(n, new HashSet());
			}
		}

		for(int qi=0; qi<M;qi++) {
			if(queries[qi][0].longValue() == 1) {
				int val = (int) queries[qi][4].longValue();
				for(Node n : nodes) {
					int level = (int) queries[qi][1].longValue();
					BigInteger l = queries[qi][2];
					BigInteger r = queries[qi][3];
					boolean isparent = false;

					if(n.level <= level) {
						BigInteger cl = convert(l, level, n.level);
						BigInteger cr = convert(r, level, n.level);
						isparent = n.pos.compareTo(cl) >= 0 && n.pos.compareTo(cr) <= 0;
					}

					if(isparent) {
						nodeToSet.get(n).add(val);
					}
				}
			} else {
				Node n = new Node((int)queries[qi][1].longValue(), queries[qi][2]);
				out.println(nodeToSet.get(n).size());
			}
		}
		out.close();
	}

	static BigInteger convert(BigInteger pos, int slevel, int tlevel) {
		return pos.divide(pow[slevel-tlevel]);
	}

	static class Node {
		public int level;
		public BigInteger pos;
		public Node(int level, BigInteger pos) {
			this.level = level;
			this.pos = pos;
		}
		@Override
		public String toString() {
			return "Node [level=" + level + ", pos=" + pos + "]";
		}
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + level;
			result = prime * result + ((pos == null) ? 0 : pos.hashCode());
			return result;
		}
		@Override
		public boolean equals(Object obj) {
			Node other = (Node) obj;
			if (level != other.level)
				return false;
			if (pos == null) {
				if (other.pos != null)
					return false;
			} else if (!pos.equals(other.pos))
				return false;
			return true;
		}
	}

	static BigInteger v(long x){
		return BigInteger.valueOf(x);
	}

	static class InputReader {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;
		private SpaceCharFilter filter;

		public InputReader(InputStream stream) {
			this.stream = stream;
		}

		public int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		public int nextInt() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-') {
				sgn = -1;
				c = read();
			}
			int res = 0;
			do {
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			return res * sgn;
		}

		public long nextLong() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-') {
				sgn = -1;
				c = read();
			}
			long res = 0;
			do {
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			return res * sgn;
		}

		public String nextToken() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public boolean isSpaceChar(int c) {
			if (filter != null)
				return filter.isSpaceChar(c);
			return isWhitespace(c);
		}

		public static boolean isWhitespace(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		public interface SpaceCharFilter {
			public boolean isSpaceChar(int ch);
		}
	}
}

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.List;

public class B {

	static PrintWriter out;
	static InputReader in;
	static long[] pow = new long[7001];
	public static void main(String[] args) throws Exception {
		in = new InputReader(System.in);
		out = new PrintWriter(System.out);

		int N = in.nextInt();
		int M = in.nextInt();

		List<Segment>[] segments = new List[N+1];
		for(int i=0; i < segments.length; i++) {
			segments[i] = new ArrayList();
		}

		int[] set = new int[1000005];
		for(int qi=0; qi<M;qi++) {
			if(in.nextInt() == 1) {
				int level = in.nextInt();
				long l = in.nextLong();
				long r = in.nextLong();
				int v = in.nextInt();
				segments[level].add(new Segment(l,r,v));
			} else {
				int level = in.nextInt();
				long pos = in.nextLong();
				long l = pos;
				long r = pos;

				int count = 0;
				while(level <= N) {
					for(Segment s : segments[level]) {
						if(s.right >= l && s.left <= r) {
							if(set[s.v] != qi) {
								set[s.v] = qi;
								count++;
							}
						}
					}
					level++;
					l = nextLeft(l);
					r = nextRight(r);
				}
				out.println(count);
			}
		}
		out.close();
	}

	static long nextLeft(long pos) {
		long hi = pos & -pos;
		if(hi == pos) {
			return pos + Long.numberOfTrailingZeros(hi);
		} else {
			return pos + Long.numberOfTrailingZeros(hi) + 1;
		}
	}
	static long nextRight(long pos) {
		return pos + Long.numberOfTrailingZeros(pos & -pos) + 1;
	}

	static class Segment {
		public long left;
		public long right;
		public int v;
		public Segment(long left, long right, int v) {
			this.left = left;
			this.right = right;
			this.v = v;
		}
	}

	static class InputReader {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;
		private SpaceCharFilter filter;

		public InputReader(InputStream stream) {
			this.stream = stream;
		}

		public int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		public int nextInt() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-') {
				sgn = -1;
				c = read();
			}
			int res = 0;
			do {
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			return res * sgn;
		}

		public long nextLong() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-') {
				sgn = -1;
				c = read();
			}
			long res = 0;
			do {
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			return res * sgn;
		}

		public String nextToken() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public boolean isSpaceChar(int c) {
			if (filter != null)
				return filter.isSpaceChar(c);
			return isWhitespace(c);
		}

		public static boolean isWhitespace(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		public interface SpaceCharFilter {
			public boolean isSpaceChar(int ch);
		}
	}
}

import java.io.*;

import java.awt.geom.Point2D;
import java.text.*;
import java.math.*;
import java.util.*;

public class Main implements Runnable {

	final String filename = "";

	int MAX = 1000001;

	public void solve() throws Exception {
		int n = iread(), m = iread();
		ArrayList<Entry>[] entries = new ArrayList[n];
		for (int i = 0; i < n; i++)
			entries[i] = new ArrayList<Entry>();
		int[] id = new int[MAX];
		for (int i = 0; i < m; i++) {
			int tp = iread();
			if (tp == 1) {
				entries[iread() - 1].add(new Entry(iread(), iread(), iread()));
			} else {
				int res = 0;
				int lvl = iread() - 1;
				int num = iread();
				int left = num, right = num;
				for (; lvl < n; lvl++) {
					for (int j = 0; j < entries[lvl].size(); j++) {
						Entry e = entries[lvl].get(j);
						if (Math.max(e.left, left) <= Math.min(e.right, right)) {
							if (id[e.x] != i + 1) {
								id[e.x] = i + 1;
								res++;
							}
						}
					}
					for (int j = 1; j <= right; j *= 2) {
						if (j < left) {
							left++;
							right++;
						} else
							right++;
					}
				}
				out.write(res + "\n");
			}
		}
	}

	class Entry implements Comparable<Entry> {
		int left, right, x;

		@Override
		public int compareTo(Entry o) {
			return x - o.x;
		}

		public Entry(int left, int right, int x) {
			super();
			this.left = left;
			this.right = right;
			this.x = x;
		}

	}

	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new BufferedWriter(new OutputStreamWriter(System.out));
			// in = new BufferedReader(new FileReader(filename+".in"));
			// out = new BufferedWriter(new FileWriter(filename+".out"));
			solve();
			out.flush();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	public int iread() throws Exception {
		return Integer.parseInt(readword());
	}

	public double dread() throws Exception {
		return Double.parseDouble(readword());
	}

	public long lread() throws Exception {
		return Long.parseLong(readword());
	}

	BufferedReader in;

	BufferedWriter out;

	public String readword() throws IOException {
		StringBuilder b = new StringBuilder();
		int c;
		c = in.read();
		while (c >= 0 && c <= ' ')
			c = in.read();
		if (c < 0)
			return "";
		while (c > ' ') {
			b.append((char) c);
			c = in.read();
		}
		return b.toString();
	}

	public static void main(String[] args) {
		try {
			Locale.setDefault(Locale.US);
		} catch (Exception e) {

		}
		// new Thread(new Main()).start();
		new Thread(null, new Main(), "1", 1 << 25).start();
	}
}

import java.io.*;
import java.util.*;

public class Main223B {

    private FastScanner in;
    private PrintWriter out;

    class Oper {
        int type;
        int level;
        int left;
        int right;
        int value;
        int position;
    }
    public void solve() throws IOException {
        int C = in.nextInt();
        int N = countLeaves(C);
        int[] parent = new int[N + 1];
        parent[1] = 1;
        int next = 2;
        int currParent = 1;
        int nextPow2 = 2;
        while(next <= N) {
            parent[next] = currParent;
            next++;
            if(currParent == nextPow2) {
                parent[next] = currParent;
                next++;
                nextPow2 *= 2;
            }
            currParent++;
        }

        int M = in.nextInt();
        Oper[] ops = new Oper[M];
        for(int i = M - 1; i >=0; i--) {
            Oper op = new Oper();
            op.type = in.nextInt();
            if(op.type == 1) {
                op.level = in.nextInt();
                op.left = in.nextInt();
                op.right = in.nextInt();
                op.value = in.nextInt();
            }
            else {
                op.level = in.nextInt();
                op.position = in.nextInt();
            }
            ops[i] = op;
        }

        Map<Integer, Map<Integer, HashSet<Integer>>> maps =
                new HashMap<Integer, Map<Integer, HashSet<Integer>>>();
        for(int i = 0; i < M; i++) {
            Oper op = ops[i];
            if(op.type == 2) {
                Map<Integer, HashSet<Integer>> ml = maps.get(op.level);
                if(ml == null) {
                    ml = new HashMap<Integer, HashSet<Integer>>();
                    maps.put(op.level, ml);
                }
                if(ml.get(op.position) == null) {
                    ml.put(op.position, new HashSet<Integer>());
                }
            }
            else {
                int left = op.left;
                int right = op.right;
                for(int j = op.level; j >= 1; j--) {
                    Map<Integer, HashSet<Integer>> ml = maps.get(j);
                    if(ml != null) {
                        for(Map.Entry<Integer, HashSet<Integer>> e : ml.entrySet()) {
                            if(e.getKey() >= left && e.getKey() <= right) {
                                e.getValue().add(op.value);
                            }
                        }
                    }
                    left = parent[left];
                    right = parent[right];
                }
            }
        }
        for(int i = M - 1; i >= 0; i--) {
            Oper op = ops[i];
            if(op.type == 2) {
                out.println(maps.get(op.level).get(op.position).size());
            }
        }
    }

    private int countLeaves(int level) {
        level--;
        int count = 1;
        int add = 1;
        while(level > 0) {
            int next = 1 << add;
            int d = next - count;
            int l = d / add;
            if(d % add != 0) {
                l++;
            }
            l = Math.min(l, level);
            level -= l;
            count += l * add;
            add++;
        }
        return count;
    }

    public void run() {
        try {
            in = new FastScanner(System.in);
            out = new PrintWriter(System.out);
            solve();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    class FastScanner {

        BufferedReader br;
        StringTokenizer st;

        FastScanner(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }
    }

    public static void main(String[] arg) {
        new Main223B().run();
    }
}

import java.io.*;
import java.util.*;

public class B {

    BufferedReader br;
    PrintWriter out;
    StringTokenizer st;
    boolean eof;

    int f(int x) {
        int ret = 0;
        while (x > 0) {
            ret++;
            x >>= 1;
        }
        return ret;
    }

    boolean isPow2(int x) {
        if (x == 0) {
            throw new AssertionError();
        }
        return (x & (x - 1)) == 0;
    }

    void solve() throws IOException {
        int n = nextInt();
        int q = nextInt();

        int[] sz = new int[n + 1];
        sz[1] = 1;
        for (int i = 1; i < n; i++) {
            sz[i + 1] = sz[i] + f(sz[i]);
        }

        int[] up = new int[sz[n] + 1];

        for (int par = 1, child = 1; child <= sz[n]; par++) {
            up[child++] = par;
            if (isPow2(par)) {
                if (child <= sz[n]) {
                    up[child++] = par;
                }
            }
        }

        List<int[]> add = new ArrayList<>();
        List<int[]> ans = new ArrayList<>();

        while (q-- > 0) {
            int type = nextInt();
            if (type == 1) {
                int[] tmp = { nextInt(), nextInt(), nextInt(), nextInt() };
                add.add(tmp);
            } else {
                int[] tmp = { nextInt(), nextInt() };
                ans.add(tmp);
            }
        }

        int[] outp = new int[ans.size()];
        Set<Integer> set = new HashSet<>();

        for (int level = n; level >= 1; level--) {
            for (int i = 0; i < ans.size(); i++) {
                if (ans.get(i)[0] == level) {
                    set.clear();
                    int pos = ans.get(i)[1];
                    for (int j = 0; j < add.size(); j++) {
                        int[] tmp = add.get(j);
//                      System.err.println(level + " " + pos);
//                      System.err
//                              .println(tmp[0] + " " + tmp[1] + " " + tmp[2]);
                        if (tmp[0] == level && tmp[1] <= pos && pos <= tmp[2]) {
                            set.add(tmp[3]);
                        }
                    }
                    outp[i] = set.size();
                }
            }

            for (int i = 0; i < add.size(); i++) {
                int[] tmp = add.get(i);
                if (tmp[0] == level) {
                    tmp[0]--;
                    tmp[1] = up[tmp[1]];
                    tmp[2] = up[tmp[2]];
                }
            }

        }

        for (int x : outp) {
            out.println(x);
        }

    }

    B() throws IOException {
        br = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);
        solve();
        out.close();
    }

    public static void main(String[] args) throws IOException {
        new B();
    }

    String nextToken() {
        while (st == null || !st.hasMoreTokens()) {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (Exception e) {
                eof = true;
                return null;
            }
        }
        return st.nextToken();
    }

    String nextString() {
        try {
            return br.readLine();
        } catch (IOException e) {
            eof = true;
            return null;
        }
    }

    int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }

    long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }

    double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }
}

//package codeforces;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class D {
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter writer = new PrintWriter(System.out);
    StringTokenizer stringTokenizer;

    String next() throws IOException {
        while (stringTokenizer == null || !stringTokenizer.hasMoreTokens()) {
            stringTokenizer = new StringTokenizer(reader.readLine());
        }
        return stringTokenizer.nextToken();
    }

    int nextInt() throws IOException {
        return Integer.parseInt(next());
    }

    long nextLong() throws IOException {
        return Long.parseLong(next());
    }

    final int MOD = 1000 * 1000 * 1000 + 7;
    int sum(int a, int b) {
        a += b;
        return a >= MOD ? a - MOD : a;
    }

    @SuppressWarnings("unchecked")
    void solve() throws IOException {
        int n = nextInt();
        int m = nextInt();
        final int LEVELS = 14;
        final int[][] parent = new int[LEVELS][100 * 1000];
        int o = 0;
        for(int i = 1; o < parent[0].length - 1; i++) {
            parent[0][++o] = i;
            if(o < parent.length - 1 && (i & (i - 1)) == 0) {
                parent[0][++o] = i;
            }
        }
        for(int l = 1; l < LEVELS; l++) {
            for(int i = 1; i < parent[l].length; i++) {
                parent[l][i] = parent[l - 1][parent[l - 1][i]];
            }
        }
        class Utils {
            int get(int levelFrom, int levelTo, int x) {
                for(int i = 0; i < LEVELS; i++) {
                    if((levelFrom - levelTo >> i) % 2 == 1) {
                        x = parent[i][x];
                    }
                }
                return x;
            }
        }
        Utils utils = new Utils();
        int[] qLevel = new int[m];
        int[] qL = new int[m];
        int[] qR = new int[m];
        int[] qX = new int[m];
        int qC = 0;
        Set<Integer> set = new HashSet<>();
        for(int i = 0; i < m; i++) {
            if(nextInt() == 1) {
                qLevel[qC] = nextInt();
                qL[qC] = nextInt();
                qR[qC] = nextInt();
                qX[qC] = nextInt();
                qC++;
            } else {
                set.clear();
                int level = nextInt();
                int v = nextInt();
                for(int k = 0; k < qC; k++) {
                    if(level > qLevel[k]) {
                        continue;
                    }
                    if(level == qLevel[k]) {
                        if(v >= qL[k] && v <= qR[k]) {
                            set.add(qX[k]);
                        }
                        continue;
                    }
                    int l = utils.get(qLevel[k], level, qL[k]);
                    int r = utils.get(qLevel[k], level, qR[k]);
                    if(v >= l && v <= r) {
                        set.add(qX[k]);
                    }
                }
                writer.println(set.size());
            }
        }
        writer.close();
    }

    public static void main(String[] args) throws IOException {
        new D().solve();
    }
}

//package codeforces;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class D {
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter writer = new PrintWriter(System.out);
    StringTokenizer stringTokenizer;

    String next() throws IOException {
        while (stringTokenizer == null || !stringTokenizer.hasMoreTokens()) {
            stringTokenizer = new StringTokenizer(reader.readLine());
        }
        return stringTokenizer.nextToken();
    }

    int nextInt() throws IOException {
        return Integer.parseInt(next());
    }

    long nextLong() throws IOException {
        return Long.parseLong(next());
    }

    final int MOD = 1000 * 1000 * 1000 + 7;
    int sum(int a, int b) {
        a += b;
        return a >= MOD ? a - MOD : a;
    }

    @SuppressWarnings("unchecked")
    void solve() throws IOException {
        int n = nextInt();
        int m = nextInt();
        final int LEVELS = 14;
        final int[][] parent = new int[LEVELS][1000 * 1000];
        int o = 0;
        for(int i = 1; o < parent[0].length - 1; i++) {
            parent[0][++o] = i;
            if(o < parent.length - 1 && (i & (i - 1)) == 0) {
                parent[0][++o] = i;
            }
        }
        for(int l = 1; l < LEVELS; l++) {
            for(int i = 1; i < parent[l].length; i++) {
                parent[l][i] = parent[l - 1][parent[l - 1][i]];
            }
        }
        class Utils {
            int get(int levelFrom, int levelTo, int x) {
                for(int i = 0; i < LEVELS; i++) {
                    if((levelFrom - levelTo >> i) % 2 == 1) {
                        x = parent[i][x];
                    }
                }
                return x;
            }
        }
        Utils utils = new Utils();
        int[] qLevel = new int[m];
        int[] qL = new int[m];
        int[] qR = new int[m];
        int[] qX = new int[m];
        int qC = 0;
        Set<Integer> set = new HashSet<>();
        for(int i = 0; i < m; i++) {
            if(nextInt() == 1) {
                qLevel[qC] = nextInt();
                qL[qC] = nextInt();
                qR[qC] = nextInt();
                qX[qC] = nextInt();
                qC++;
            } else {
                set.clear();
                int level = nextInt();
                int v = nextInt();
                for(int k = 0; k < qC; k++) {
                    if(level > qLevel[k]) {
                        continue;
                    }
                    int l = utils.get(qLevel[k], level, qL[k]);
                    int r = utils.get(qLevel[k], level, qR[k]);
                    if(v >= l && v <= r) {
                        set.add(qX[k]);
                    }
                }
                writer.println(set.size());
            }
        }
        writer.close();
    }

    public static void main(String[] args) throws IOException {
        new D().solve();
    }
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Comparator;
import java.util.HashSet;
import java.util.StringTokenizer;
import java.util.TreeSet;

public class Round223_Div2_D {
  static class Struct {
    int level, st, end, x;

    public Struct(int l, int s, int e, int xx) {
      level = l;
      st = s;
      end = e;
      x = xx;
    }
  }

  public static void main(String[] args) throws Exception {
    PrintWriter out = new PrintWriter(System.out);
    int levelCnt = nextInt();
    int queryCnt = nextInt();
    TreeSet<Struct> structs = new TreeSet<>(new Comparator<Struct>() {
      @Override
      public int compare(Struct o1, Struct o2) {
        return new Integer(o1.level).compareTo(o2.level);
      }
    });
    for (int i = 0; i < queryCnt; i++) {
      int queryT = nextInt();
      if (queryT == 1) {
        structs.add(new Struct(nextInt(), nextInt(), nextInt(), nextInt()));
      } else {
        int level = nextInt();
        int pos = nextInt();
        HashSet<Integer> set = new HashSet<>();
        int st=pos,end=pos;
        for (Struct s : structs) {
          if(s.level<level) continue;
          while(level < s.level) {
            int allbit=Integer.highestOneBit(end);
            int before=Integer.highestOneBit(st-1);
            int mine=allbit-before;
            int diff = end-st;
            st=st+before;
            end=st+diff+mine;
//            if(i==2){
//              System.out.println(st+" "+end+" "+diff+" "+mine+" "+allbit+" "+before);
//            }
            level++;
          }
//          System.out.println(level+" "+st+" "+end+" a7a "+(i)+" ");
//          System.out.println("a7eh "+s.st+" "+s.end);
          if(!(st>s.end||end<s.st)) {
            set.add(s.x);
          }
        }
        out.println(set.size());
      }
    }
    out.flush();
  }

  static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  static StringTokenizer tokenizer = new StringTokenizer("");

  static int nextInt() throws Exception {
    return Integer.parseInt(next());
  }

  static double nextDouble() throws Exception {
    return Double.parseDouble(next());
  }

  static String next() throws Exception {
    while (true) {
      if (tokenizer.hasMoreTokens()) {
        return tokenizer.nextToken();
      }
      String s = br.readLine();
      if (s == null) {
        return null;
      }
      tokenizer = new StringTokenizer(s);
    }
  }
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Comparator;
import java.util.HashSet;
import java.util.StringTokenizer;
import java.util.TreeSet;

public class Round223_Div2_D {
  static class Struct {
    int level, st, end, x;

    public Struct(int l, int s, int e, int xx) {
      level = l;
      st = s;
      end = e;
      x = xx;
    }
  }

  public static int highestOneBit(int x){
    int i=1;
    int res=0;
    int idx=1;
    while(i<=x) {
      if((x|i) == x) {
        res=idx;
      }
      idx++;
      i<<=1;
    }
    return res;
  }

  public static void main(String[] args) throws Exception {
    PrintWriter out = new PrintWriter(System.out);
    int levelCnt = nextInt();
    int queryCnt = nextInt();
    TreeSet<Struct> structs = new TreeSet<>(new Comparator<Struct>() {
      @Override
      public int compare(Struct o1, Struct o2) {
        return new Integer(o1.level).compareTo(o2.level);
      }
    });
    for (int i = 0; i < queryCnt; i++) {
      int queryT = nextInt();
      if (queryT == 1) {
        structs.add(new Struct(nextInt(), nextInt(), nextInt(), nextInt()));
      } else {
        int level = nextInt();
        int pos = nextInt();
        HashSet<Integer> set = new HashSet<>();
        int st=pos,end=pos;
        for (Struct s : structs) {
          if(s.level<level) continue;
          while(level < s.level) {
            int allbit=highestOneBit(end);
            int before=highestOneBit(st-1);
            int mine=allbit-before;
            int diff = end-st;
//            System.out.println(st+" "+end+" "+(level+1)+" "+diff+" "+mine+" "+before+" "+Integer.highestOneBit(st-1));
            st=st+before;
            end=st+diff+mine;
//            if(i==0){

//            }
            level++;
          }
//          System.out.println(level+" "+st+" "+end+" a7a "+(i)+" ");
//          System.out.println("a7eh "+s.st+" "+s.end);
          if(!(st>s.end||end<s.st)) {
            set.add(s.x);
          }
        }
        out.println(set.size());
      }
    }
    out.flush();
  }

  static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  static StringTokenizer tokenizer = new StringTokenizer("");

  static int nextInt() throws Exception {
    return Integer.parseInt(next());
  }

  static double nextDouble() throws Exception {
    return Double.parseDouble(next());
  }

  static String next() throws Exception {
    while (true) {
      if (tokenizer.hasMoreTokens()) {
        return tokenizer.nextToken();
      }
      String s = br.readLine();
      if (s == null) {
        return null;
      }
      tokenizer = new StringTokenizer(s);
    }
  }
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

/**
 * @author Don Li
 */
public class SerejaTree {

    int N = 7001;

    void solve() {
        int n = in.nextInt(), m = in.nextInt();
        List<Segment> segments = new ArrayList<>();
        int[] L = new int[N], R = new int[N];
        for (int i = 0; i < m; i++) {
            int type = in.nextInt();
            if (type == 1) {
                int t = in.nextInt(), l = in.nextInt(), r = in.nextInt(), x = in.nextInt();
                segments.add(new Segment(t, l, r, x));
            } else {
                int t = in.nextInt(), v = in.nextInt();
                L[t] = v;
                R[t] = v;
                for (int j = t + 1; j <= n; j++) {
                    L[j] = L[j - 1] + count(L[j - 1] - 1);
                    R[j] = R[j - 1] + count(R[j - 1]);
                }

                Set<Integer> set = new HashSet<>();
                for (Segment seg : segments) {
                    if (seg.t < t) continue;
                    if (L[seg.t] > seg.r || R[seg.t] < seg.l) continue;
                    set.add(seg.x);
                }
                out.println(set.size());
            }
        }
    }

    int count(int n) {
        return Integer.numberOfTrailingZeros(Integer.highestOneBit(n)) + 1;
    }

    static class Segment {
        int t, l, r, x;

        public Segment(int t, int l, int r, int x) {
            this.t = t;
            this.l = l;
            this.r = r;
            this.x = x;
        }
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new SerejaTree().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(nextToken());
        }

        public long nextLong() {
            return Long.parseLong(nextToken());
        }

        public double nextDouble() {
            return Double.parseDouble(nextToken());
        }
    }
}

import java.util.TreeSet;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.Set;
import java.util.StringTokenizer;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskD solver = new TaskD();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskD {

    int[] t = new int[20];

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt(), m = in.nextInt();

        t[0] = 1;
        for (int i = 1; i < 20; i++) {
            t[i] = t[i - 1] * 2;
        }

        OP[] ops = new OP[m];
        for (int i = 0; i < m; i++) {
            OP op = new OP();
            ops[i] = op;
            op.type = in.nextInt();
            if (op.type == 1) {
                op.level = in.nextInt();
                op.left = in.nextInt();
                op.right = in.nextInt();
                op.element = in.nextInt();
            } else {
                op.level = in.nextInt();
                op.pos = in.nextInt();
                op.set = new TreeSet<>();
            }
        }

        int[] ll = new int[n + 1];
        int[] lr = new int[n + 1];

        for (int i = m - 1; i >= 0; i--) {
            OP o = ops[i];
            if (o.type == 1) {
                buildPath(ll, o.level, o.left);
                buildPath(lr, o.level, o.right);
                for (int h = i + 1; h < m; h++) {
                    if (ops[h].type == 2) {
                        OP oo = ops[h];
                        if (ll[oo.level] <= oo.pos && oo.pos <= lr[oo.level]) {
                            oo.set.add(o.element);
                        }
                    }
                }
            }
        }

        for (int i = 0; i < m; i++) {
            if (ops[i].type == 2) {
                out.println(ops[i].set.size());
            }
        }

    }

    void buildPath(int[] levels, int level, int pos) {
        levels[level] = pos;

        for (int l = level - 1; l >= 1; l--) {
            int i = 0;
            int curp = 0, ans = 0;
            pos = levels[l + 1];

            while (true) {
                if (curp + 2 >= pos) {
                    ans = t[i];
                    break;
                } else if (curp + 2 + t[i + 1] - t[i] - 1 >= pos) {
                    ans = t[i] + (pos - curp - 2);
                    break;
                }
                curp += 2 + t[i + 1] - t[i] - 1;
                i++;
            }

            levels[l] = ans;
        }
    }

    public static class OP {
        int type;
        int left, right;
        int element;

        int level, pos;
        Set<Integer> set;
    }
}

class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream), 32768);
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

}

import java.util.TreeSet;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.StringTokenizer;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskD solver = new TaskD();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskD {
    public int[] two = new int[20];

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt(), m = in.nextInt();
        two[0] = 1;
        for (int i = 1; i < 20; i++) {
            two[i] = two[i - 1] * 2;
        }
        SET[] sets = new SET[m];
        int mm = 0;
        TreeSet<Integer> ansSet = new TreeSet<>();
        for (int i = 0; i < m; i++) {
            int type = in.nextInt();
            if (type == 1) {
                sets[mm] = new SET();
                sets[mm].level = in.nextInt();
                sets[mm].left = in.nextInt();
                sets[mm].right = in.nextInt();
                sets[mm].set = in.nextInt();
                mm++;
            } else {
                int level = in.nextInt();
                int pos = in.nextInt();
                ansSet.clear();
                for (int h = 0; h < mm; h++) {
                    if (level <= sets[h].level && posForLevel(level, sets[h].level, sets[h].left) <= pos &&
                            posForLevel(level, sets[h].level, sets[h].right) >= pos) {
                        ansSet.add(sets[h].set);
                    }
                }
                out.println(ansSet.size());
            }
        }
    }

    public int posForLevel(int tar_l, int cur_l, int cur_p) {
        int qp = 0, curt = 0;
        int ld = two[Math.min(19, cur_l - tar_l)];
        int dest = 0;
        while (true) {
            if (qp + ld >= cur_p) {
                dest = two[curt];
                break;
            } else if (qp + ld + two[curt + 1] - two[curt] - 1 >= cur_p) {
                dest = two[curt] + qp + ld + two[curt + 1] - two[curt] - 1 - cur_p;
                break;
            }
            qp += ld + two[curt + 1] - two[curt] - 1;
            curt++;
        }
        return dest;
    }

    public static class SET {
        int level;
        int left, right;
        int set;
    }
}

class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream), 32768);
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

}

import java.io.*;
import java.util.*;

public class B {
    public static void main(String[] args) throws Exception {
        new B().solve();
        // new FileInputStream(new File("input.txt")),
        // new PrintStream(new FileOutputStream(new File("output.txt"))));
    }

    void solve() throws IOException {
        BufferedReader in = new BufferedReader(new
                InputStreamReader(System.in));
        Scanner sc = new Scanner(System.in);
        String[] sp;

        // n, m
        sp = in.readLine().split(" ");
        int n = Integer.parseInt(sp[0]);
        int m = Integer.parseInt(sp[1]);

        // par
        par2 = new int[15][140000];
        {
            // 1
            int nci = 1;
            for (int pos = 1; nci < par2[0].length; pos++) {
                if ((pos & -pos) == pos) {// 2^k
                    par2[0][nci++] = pos;
                    par2[0][nci++] = pos;
                } else {
                    par2[0][nci++] = pos;
                }
            }
            // 2~
            for (int lv2 = 1; lv2 < par2.length; lv2++) {
                for (int pos = 1; pos < par2[0].length; pos++) {
                    par2[lv2][pos] = par2[lv2 - 1][par2[lv2 - 1][pos]];
                }
            }
        }

        int size = 0;
        int[] level = new int[m];
        int[] left = new int[m];
        int[] right = new int[m];
        int[] x = new int[m];
        int[] flg = new int[2000000];
        StringBuilder sb = new StringBuilder();

        // operations
        for (int i = 0; i < m; i++) {
            sp = in.readLine().split(" ");
            int op = Integer.parseInt(sp[0]);
            if (op == 1) {
                level[size] = Integer.parseInt(sp[1]);
                left[size] = Integer.parseInt(sp[2]);
                right[size] = Integer.parseInt(sp[3]);
                x[size] = Integer.parseInt(sp[4]);
                size++;
            } else {// 2
                int lv2 = Integer.parseInt(sp[1]);
                int p = Integer.parseInt(sp[2]);
                int count = 0;

                for (int ai = 0; ai < size; ai++) {
                    int lv1 = level[ai];
                    if (lv2 <= lv1) {
                        int l = par(lv1 - lv2, left[ai]);
                        int r = par(lv1 - lv2, right[ai]);
                        if (l <= p && p <= r && flg[x[ai]] != i) {
                            flg[x[ai]] = i;
                            count++;
                        }
                    }
                }
                sb.append(count + "\n");
            }
        }
        System.out.print(sb);
    }
    int[][] par2;
    int par(int lv, int pos) {
        for (int b = 0; (lv >> b) > 0; b++) {
            pos = par2[b][pos] * (lv >> b & 1);
        }
        return pos;
    }
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//