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.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());
    }

    }

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.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());
    }

}

//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.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.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.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.*;
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.*;
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.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.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.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.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;
    }
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//