#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vi> vvi;
typedef pair<int, int> pii;
typedef vector<pii> vii;
typedef vector<bool> vb;
typedef vector<string> vs;
const int di[] = { -1, 0, 1, 0, -1, 1, 1, -1 };
const int dj[] = { 0, 1, 0, -1, -1, 1, -1, 1 };
const ll MOD = 1e9 + 7;
const ll INF = 1e9;
const long double EPS = 1e-7;
#define all(x) x.begin(),x.end()

class SegmentTree {         // the segment tree is stored like a heap array
private: vi st, A;            // recall that vi is: typedef vector<int> vi;
		 int n;
		 int left(int p) { return p << 1; }     // same as binary heap operations
		 int right(int p) { return (p << 1) + 1; }

		 void build(int p, int L, int R) {                           // O(n log n)
			 if (L == R)                            // as L == R, either one is fine
				 st[p] = L;                                         // store the index
			 else {                                // recursively compute the values
				 build(left(p), L, (L + R) / 2);
				 build(right(p), (L + R) / 2 + 1, R);
				 int p1 = st[left(p)], p2 = st[right(p)];
				 st[p] = (A[p1] >= A[p2]) ? p1 : p2;
			 }
		 }

		 int rmq(int p, int L, int R, int i, int j) {                  // O(log n)
			 if (i > R || j < L) return -1; // current segment outside query range
			 if (L >= i && R <= j) return st[p];               // inside query range

															   // compute the min position in the left and right part of the interval
			 int p1 = rmq(left(p), L, (L + R) / 2, i, j);
			 int p2 = rmq(right(p), (L + R) / 2 + 1, R, i, j);

			 if (p1 == -1) return p2;   // if we try to access segment outside query
			 if (p2 == -1) return p1;                               // same as above
			 return (A[p1] >= A[p2]) ? p1 : p2;
		 }          // as as in build routine

		 int update_point(int p, int L, int R, int idx, int new_value) {
			 // this update code is still preliminary, i == j
			 // must be able to update range in the future!
			 int i = idx, j = idx;

			 // if the current interval does not intersect
			 // the update interval, return this st node value!
			 if (i > R || j < L)
				 return st[p];

			 // if the current interval is included in the update range,
			 // update that st[node]
			 if (L == i && R == j) {
				 A[i] = new_value; // update the underlying array
				 return st[p] = L; // this index
			 }

			 // compute the minimum pition in the
			 // left and right part of the interval
			 int p1, p2;
			 p1 = update_point(left(p), L, (L + R) / 2, idx, new_value);
			 p2 = update_point(right(p), (L + R) / 2 + 1, R, idx, new_value);

			 // return the pition where the overall minimum is
			 return st[p] = (A[p1] >= A[p2]) ? p1 : p2;
		 }

public:
	SegmentTree(const vi &_A) {
		A = _A; n = (int)A.size();              // copy content for local usage
		st.assign(4 * n, 0);            // create large enough vector of zeroes
		build(1, 0, n - 1);                                  // recursive build
	}

	int rmq(int i, int j) { return A[rmq(1, 0, n - 1, i, j)]; }   // overloading

	int update_point(int idx, int new_value) {
		return update_point(1, 0, n - 1, idx, new_value);
	}
};

struct Edge {
	int v, w;
};

int n, m;
vvi adj, adjSz;
vector<Edge> edge;
vector<SegmentTree> seg;

bool cmp(int a, int b) {
	return edge[a].w < edge[b].w;
}

vi mem(3e5 + 5, -1);
int solve(int idx) {
	int& ret = mem[idx];
	if (~ret) return ret;
	ret = 0;

	int u = edge[idx].v;
	int w = edge[idx].w;

	auto it = upper_bound(all(adjSz[u]), w);
	int start = it - adjSz[u].begin();
	for (int i = start; i < adj[u].size(); i++) {
		if (~mem[adj[u][i]]) {
			ret = max(ret, seg[u].rmq(i, adj[u].size() - 1));
			break;
		}
		int x = solve(adj[u][i]);
		seg[u].update_point(i, x);
		ret = max(ret, x);
	}
	return ++ret;
}

int main() {
	ios::sync_with_stdio(false), cin.tie(0);
	cin >> n >> m;
	adj.assign(n, vi());
	for (int i = 0; i < m; i++) {
		int u, v, w; cin >> u >> v >> w;
		u--, v--;
		adj[u].push_back(edge.size());
		edge.push_back({ v,w });
	}

	adjSz.resize(n);
	for (int i = 0; i < n; i++) {
		sort(all(adj[i]), cmp);
		adjSz[i].resize(adj[i].size());
		for (int j = 0; j < adj[i].size(); j++)
			adjSz[i][j] = edge[adj[i][j]].w;

		vi A(adj.size());
		seg.emplace_back(A);
	}

	int r = 0;
	for (int i = 0; i < m; i++)
		r = max(r, solve(i));
	cout << r << endl;
	cin.ignore(), cin.get();
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vi> vvi;
typedef pair<int, int> pii;
typedef vector<pii> vii;
typedef vector<bool> vb;
typedef vector<string> vs;
const int di[] = { -1, 0, 1, 0, -1, 1, 1, -1 };
const int dj[] = { 0, 1, 0, -1, -1, 1, -1, 1 };
const ll MOD = 1e9 + 7;
const ll INF = 1e9;
const long double EPS = 1e-7;
#define all(x) x.begin(),x.end()

class SegmentTree {         // the segment tree is stored like a heap array
private: vi st, A;            // recall that vi is: typedef vector<int> vi;
		 int n;
		 int left(int p) { return p << 1; }     // same as binary heap operations
		 int right(int p) { return (p << 1) + 1; }

		 void build(int p, int L, int R) {                           // O(n log n)
			 if (L == R)                            // as L == R, either one is fine
				 st[p] = L;                                         // store the index
			 else {                                // recursively compute the values
				 build(left(p), L, (L + R) / 2);
				 build(right(p), (L + R) / 2 + 1, R);
				 int p1 = st[left(p)], p2 = st[right(p)];
				 st[p] = (A[p1] >= A[p2]) ? p1 : p2;
			 }
		 }

		 int rmq(int p, int L, int R, int i, int j) {                  // O(log n)
			 if (i > R || j < L) return -1; // current segment outside query range
			 if (L >= i && R <= j) return st[p];               // inside query range

															   // compute the min position in the left and right part of the interval
			 int p1 = rmq(left(p), L, (L + R) / 2, i, j);
			 int p2 = rmq(right(p), (L + R) / 2 + 1, R, i, j);

			 if (p1 == -1) return p2;   // if we try to access segment outside query
			 if (p2 == -1) return p1;                               // same as above
			 return (A[p1] >= A[p2]) ? p1 : p2;
		 }          // as as in build routine

		 int update_point(int p, int L, int R, int idx, int new_value) {
			 // this update code is still preliminary, i == j
			 // must be able to update range in the future!
			 int i = idx, j = idx;

			 // if the current interval does not intersect
			 // the update interval, return this st node value!
			 if (i > R || j < L)
				 return st[p];

			 // if the current interval is included in the update range,
			 // update that st[node]
			 if (L == i && R == j) {
				 A[i] = new_value; // update the underlying array
				 return st[p] = L; // this index
			 }

			 // compute the minimum pition in the
			 // left and right part of the interval
			 int p1, p2;
			 p1 = update_point(left(p), L, (L + R) / 2, idx, new_value);
			 p2 = update_point(right(p), (L + R) / 2 + 1, R, idx, new_value);

			 // return the pition where the overall minimum is
			 return st[p] = (A[p1] >= A[p2]) ? p1 : p2;
		 }

public:
	SegmentTree(const vi &_A) {
		if (_A.empty()) return;
		A = _A; n = (int)A.size();              // copy content for local usage
		st.assign(4 * n, 0);            // create large enough vector of zeroes
		build(1, 0, n - 1);                                  // recursive build
	}

	int rmq(int i, int j) { return A[rmq(1, 0, n - 1, i, j)]; }   // overloading

	int update_point(int idx, int new_value) {
		return update_point(1, 0, n - 1, idx, new_value);
	}
};

struct Edge {
	int v, w;
};

int n, m;
vvi adj, adjSz;
vector<Edge> edge;
vector<SegmentTree> seg;

bool cmp(int a, int b) {
	return edge[a].w < edge[b].w;
}

vi mem(3e5 + 5, -1);
int solve(int idx) {
	int& ret = mem[idx];
	if (~ret) return ret;
	ret = 0;

	int u = edge[idx].v;
	int w = edge[idx].w;

	auto it = upper_bound(all(adjSz[u]), w);
	int start = it - adjSz[u].begin();
	for (int i = start; i < adj[u].size(); i++) {
		if (~mem[adj[u][i]]) {
			ret = max(ret, seg[u].rmq(i, adj[u].size() - 1));
			break;
		}
		int x = solve(adj[u][i]);
		seg[u].update_point(i, x);
		ret = max(ret, x);
	}
	return ++ret;
}

int main() {
	ios::sync_with_stdio(false), cin.tie(0);
	cin >> n >> m;
	adj.assign(n, vi());
	for (int i = 0; i < m; i++) {
		int u, v, w; cin >> u >> v >> w;
		u--, v--;
		adj[u].push_back(edge.size());
		edge.push_back({ v,w });
	}

	adjSz.resize(n);
	for (int i = 0; i < n; i++) {
		sort(all(adj[i]), cmp);
		adjSz[i].resize(adj[i].size());
		for (int j = 0; j < adj[i].size(); j++)
			adjSz[i][j] = edge[adj[i][j]].w;

		vi A(adj[i].size());
		seg.push_back(SegmentTree(A));
	}

	int r = 0;
	for (int i = 0; i < m; i++)
		r = max(r, solve(i));
	cout << r << endl;
	cin.ignore(), cin.get();
}


#include<stdio.h>
//#include<bits/stdc++.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<sstream>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include<algorithm>
#include<limits.h>
#define inf 0x7fffffff
#define INFL 0x7fffffffffffffff
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define ULL unsigned long long
using namespace std;
const int M = 2000000;
int n,m;
struct P
{
    int v,u,w;
}H[M];
bool solve(P x,P y)
{
    return x.w<y.w;
}
int dp[M],ans[M];
int j;
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        cin>>H[i].v>>H[i].u>>H[i].w;
    }
    sort(H,H+n,solve);
    for(int i=0;i<m;i=j)
    {
        for(j=i;H[i].w==H[j].w&&j<m;j++)
        {
            ans[H[j].u]=dp[H[j].u];
        }
        for(j=i;H[i].w==H[j].w&&j<m;j++)
        {
            ans[H[j].u]=max(ans[H[j].u],dp[H[j].v]+1);
        }
        for(j=i;H[i].w==H[j].w&&j<m;j++)
        {
            dp[H[j].u]=ans[H[j].u];
        }
    }
    int Max=-1;
    for(int i=1;i<=n;i++)
    {
        Max=max(dp[i],Max);
    }
    cout<<Max<<endl;
    return 0;
}


#include<stdio.h>
//#include<bits/stdc++.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<sstream>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include<algorithm>
#include<limits.h>
#define inf 0x7fffffff
#define INFL 0x7fffffffffffffff
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define ULL unsigned long long
using namespace std;
const int M = 200000;
int n,m;
struct P
{
    int v,u,w;
}H[M];
bool solve(P x,P y)
{
    return x.w<y.w;
}
int dp[M],ans[M];
int j;
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        cin>>H[i].v>>H[i].u>>H[i].w;
    }
    sort(H,H+n,solve);
    for(int i=0;i<n;i=j)
    {
        for(j=i;H[i].w==H[j].w&&j<n;j++)
        {
            ans[H[j].u]=dp[H[j].u];
        }
        for(j=i;H[i].w==H[j].w&&j<n;j++)
        {
            ans[H[j].u]=max(ans[H[j].u],dp[H[j].v]+1);
        }
        for(j=i;H[i].w==H[j].w&&j<n;j++)
        {
            dp[H[j].u]=ans[H[j].u];
        }
    }
    cout<<*max_element(dp,dp+n+1)<<endl;
    return 0;
}


#include<stdio.h>
//#include<bits/stdc++.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<sstream>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include<algorithm>
#include<limits.h>
#define inf 0x7fffffff
#define INFL 0x7fffffffffffffff
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define ULL unsigned long long
using namespace std;
const int M = 2000000;
int n,m;
struct P
{
    int v,u,w;
}H[M];
bool solve(P x,P y)
{
    return x.w<y.w;
}
int dp[M],ans[M];
int j;
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        cin>>H[i].v>>H[i].u>>H[i].w;
    }
    sort(H,H+m,solve);
    for(int i=0;i<m;i=j)
    {
        for(j=i;H[i].w==H[j].w&&j<m;j++)
        {
            ans[H[j].u]=dp[H[j].u];
        }
        for(j=i;H[i].w==H[j].w&&j<m;j++)
        {
            ans[H[j].u]=max(ans[H[j].u],dp[H[j].v]+1);
        }
        for(j=i;H[i].w==H[j].w&&j<m;j++)
        {
            dp[H[j].u]=ans[H[j].u];
        }
    }
    int Max=-1;
    for(int i=1;i<=n;i++)
    {
        Max=max(dp[i],Max);
    }
    cout<<Max<<endl;
    return 0;
}


#include<stdio.h>
//#include<bits/stdc++.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<sstream>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include<algorithm>
#include<limits.h>
#define inf 0x7fffffff
#define INFL 0x7fffffffffffffff
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define ULL unsigned long long
using namespace std;
const int M = 200000;
int n,m;
struct P
{
    int v,u,w;
}H[M];
bool solve(P x,P y)
{
    return x.w<y.w;
}
int dp[M],ans[M];
int j;
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        cin>>H[i].v>>H[i].u>>H[i].w;
    }
    sort(H,H+m,solve);
    for(int i=0;i<m;i=j)
    {
        for(j=i;H[i].w==H[j].w&&j<m;j++)
        {
            ans[H[j].u]=dp[H[j].u];
        }
        for(j=i;H[i].w==H[j].w&&j<m;j++)
        {
            ans[H[j].u]=max(ans[H[j].u],dp[H[j].v]+1);
        }
        for(j=i;H[i].w==H[j].w&&j<m;j++)
        {
            dp[H[j].u]=ans[H[j].u];
        }
    }
    cout<<*max_element(dp,dp+n+1)<<endl;
    return 0;
}


#include<stdio.h>
//#include<bits/stdc++.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<sstream>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include<algorithm>
#include<limits.h>
#define inf 0x7fffffff
#define INFL 0x7fffffffffffffff
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define ULL unsigned long long
using namespace std;
const int M = 2000000;
int n,m;
struct P
{
    int v,u,w;
}H[M];
bool solve(P x,P y)
{
    return x.w<y.w;
}
int dp[M],ans[M];
int j;
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        cin>>H[i].v>>H[i].u>>H[i].w;
    }
    sort(H,H+n,solve);
    for(int i=0;i<m;i=j)
    {
        for(j=i;H[i].w==H[j].w&&j<m;j++)
        {
            ans[H[j].u]=dp[H[j].u];
        }
        for(j=i;H[i].w==H[j].w&&j<m;j++)
        {
            ans[H[j].u]=max(ans[H[j].u],dp[H[j].v]+1);
        }
        for(j=i;H[i].w==H[j].w&&j<m;j++)
        {
            dp[H[j].u]=ans[H[j].u];
        }
    }
    int Max=-1;
    for(int i=1;i<=n;i++)
    {
        Max=max(dp[i],Max);
    }
    cout<<Max<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define M 5010
#define N 20000010

int root[5][M][M], ans[100010];

int L[N], R[N], tot, s[N], m;

void update(int &id, int l, int r, int x) {

	if (!id) id = ++tot;

	if (l == r) {
		s[id]++; return;
	}

	int mid = (l + r) >> 1;

	if (x <= mid) update(L[id], l, mid, x);
	else update(R[id], mid + 1, r, x);

	s[id] = s[L[id]] + s[R[id]];

}

int calc(int id, int st, int en, int l, int r) {
	if (!id) return 0;
	if (l <= st && en <= r) return s[id];

	int mid = (st + en) >> 1;
	int res = 0;
	if (l <= mid) res += calc(L[id], st, mid, l, r);
	if (mid < r) res += calc(R[id], mid + 1, en, l, r);
	return res;
}

int n, Q;

struct dat {
	int type, dir, x, y, len;
	dat(int type = 0, int dir = 0, int x = 0, int y = 0, int len = 0) : type(type), dir(dir), x(x), y(y), len(len) {}
} q[100010];

int main() {
//freopen("I.in", "r", stdin);
	scanf("%d %d", &n, &Q);

	int dir, x, y, t, len, xx, yy;
	m = 2 * n;
	for (int i = 0; i < Q; i++) {
		scanf("%d", &t);
		if (t == 1) {
			scanf("%d %d %d %d", &dir, &x, &y, &len);
			q[i] = dat(t, dir, x, y, len);
		}
		else {
			scanf("%d %d", &x, &y);
			q[i] = dat(t, 0, x, y);
		}
	}
	for (int t = 1; t <= 4; t++) {
		for (int i = 0; i < Q; i++) {
			if (q[i].type == 1) {

				if (t != q[i].dir) continue;

				if (t == 1) {
					x = q[i].x, y = q[i].y;
				}
				else if (t == 2) {
					x = q[i].x, y = n - q[i].y + 1;
				}
				else if (t == 3) {
					x = n - q[i].x + 1, y = q[i].y;
				}
				else {
					x = n - q[i].x + 1, y = n - q[i].y + 1;
				}

				int tx = x, ty = y;
				for ( ; x <= n; x += (x & -x)) {
					yy = y;
					for ( ; yy <= n; yy += (yy & -yy)) update(root[t][x][yy], 1, m, tx + ty + q[i].len);
				}
			}
			else {
				if (t == 1) {
					x = q[i].x, y = q[i].y;
				}
				else if (t == 2) {
					x = q[i].x, y = n - q[i].y + 1;
				}
				else if (t == 3) {
					x = n - q[i].x + 1, y = q[i].y;
				}
				else {
					x = n - q[i].x + 1, y = n - q[i].y + 1;
				}
				int tx = x, ty = y;
				for ( ; x; x -= (x & -x)) {
					yy = y;
					for ( ; yy; yy -= (yy & -yy)) {
						ans[i] += calc(root[t][x][yy], 1, m, tx + ty, m);
					}
				}
			}
		}
	}
	for (int i = 0; i < Q; i++) {
		if (q[i].type == 2) printf("%d\n",ans[i]);
	}
}


#include <bits/stdc++.h>
using namespace std;
#define M 5010
#define N 30000010

int root[5][M][M], ans[100010];

int L[N], R[N], tot, s[N], m;

void update(int &id, int l, int r, int x) {

	if (!id) id = ++tot;

	if (l == r) {
		s[id]++; return;
	}

	int mid = (l + r) >> 1;

	if (x <= mid) update(L[id], l, mid, x);
	else update(R[id], mid + 1, r, x);

	s[id] = s[L[id]] + s[R[id]];

}

int calc(int id, int st, int en, int l, int r) {
	if (!id) return 0;
	if (l <= st && en <= r) return s[id];

	int mid = (st + en) >> 1;
	int res = 0;
	if (l <= mid) res += calc(L[id], st, mid, l, r);
	if (mid < r) res += calc(R[id], mid + 1, en, l, r);
	return res;
}

int n, Q;

struct dat {
	int type, dir, x, y, len;
	dat(int type = 0, int dir = 0, int x = 0, int y = 0, int len = 0) : type(type), dir(dir), x(x), y(y), len(len) {}
} q[100010];

int main() {
//freopen("I.in", "r", stdin);
	scanf("%d %d", &n, &Q);

	int dir, x, y, t, len, xx, yy;
	m = 2 * n;
	for (int i = 0; i < Q; i++) {
		scanf("%d", &t);
		if (t == 1) {
			scanf("%d %d %d %d", &dir, &x, &y, &len);
			q[i] = dat(t, dir, x, y, len);
		}
		else {
			scanf("%d %d", &x, &y);
			q[i] = dat(t, 0, x, y);
		}
	}
	for (int t = 1; t <= 4; t++) {
		for (int i = 0; i < Q; i++) {
			if (q[i].type == 1) {

				if (t != q[i].dir) continue;

				if (t == 1) {
					x = q[i].x, y = q[i].y;
				}
				else if (t == 2) {
					x = q[i].x, y = n - q[i].y + 1;
				}
				else if (t == 3) {
					x = n - q[i].x + 1, y = q[i].y;
				}
				else {
					x = n - q[i].x + 1, y = n - q[i].y + 1;
				}

				int tx = x, ty = y;
				for ( ; x <= n; x += (x & -x)) {
					yy = y;
					for ( ; yy <= n; yy += (yy & -yy)) update(root[t][x][yy], 1, m, tx + ty + q[i].len);
				}
			}
			else {
				if (t == 1) {
					x = q[i].x, y = q[i].y;
				}
				else if (t == 2) {
					x = q[i].x, y = n - q[i].y + 1;
				}
				else if (t == 3) {
					x = n - q[i].x + 1, y = q[i].y;
				}
				else {
					x = n - q[i].x + 1, y = n - q[i].y + 1;
				}
				int tx = x, ty = y;
				for ( ; x; x -= (x & -x)) {
					yy = y;
					for ( ; yy; yy -= (yy & -yy)) {
						ans[i] += calc(root[t][x][yy], 1, m, tx + ty, m);
					}
				}
			}
		}
	}
	for (int i = 0; i < Q; i++) {
		if (q[i].type == 2) printf("%d\n",ans[i]);
	}
}


#include <bits/stdc++.h>
using namespace std;
#define M 5010
#define N 30000010

int root[M][M], ans[100010];

int L[N], R[N], tot, s[N], m;

void update(int &id, int l, int r, int x) {

	if (!id) id = ++tot;

	if (l == r) {
		s[id]++; return;
	}

	int mid = (l + r) >> 1;

	if (x <= mid) update(L[id], l, mid, x);
	else update(R[id], mid + 1, r, x);

	s[id] = s[L[id]] + s[R[id]];

}

int calc(int id, int st, int en, int l, int r) {
	if (!id) return 0;
	if (l <= st && en <= r) return s[id];

	int mid = (st + en) >> 1;
	int res = 0;
	if (l <= mid) res += calc(L[id], st, mid, l, r);
	if (mid < r) res += calc(R[id], mid + 1, en, l, r);
	return res;
}

int n, Q;

struct dat {
	int type, dir, x, y, len;
	dat(int type = 0, int dir = 0, int x = 0, int y = 0, int len = 0) : type(type), dir(dir), x(x), y(y), len(len) {}
} q[100010];

int main() {
//freopen("I.in", "r", stdin);
	scanf("%d %d", &n, &Q);

	int dir, x, y, t, len, xx, yy;
	m = 2 * n;
	for (int i = 0; i < Q; i++) {
		scanf("%d", &t);
		if (t == 1) {
			scanf("%d %d %d %d", &dir, &x, &y, &len);
			q[i] = dat(t, dir, x, y, len);
		}
		else {
			scanf("%d %d", &x, &y);
			q[i] = dat(t, 0, x, y);
		}
	}
	for (int t = 1; t <= 4; t++) {
		if (t > 1) {
			memset(root, 0, sizeof(root));
			for (int i = 0; i <= tot; i++) L[i] = R[i] = s[i] = 0;
			tot = 0;
		}
		for (int i = 0; i < Q; i++) {
			if (q[i].type == 1) {

				if (t != q[i].dir) continue;

				if (t == 1) {
					x = q[i].x, y = q[i].y;
				}
				else if (t == 2) {
					x = q[i].x, y = n - q[i].y + 1;
				}
				else if (t == 3) {
					x = n - q[i].x + 1, y = q[i].y;
				}
				else {
					x = n - q[i].x + 1, y = n - q[i].y + 1;
				}

				int tx = x, ty = y;
				for ( ; x <= n; x += (x & -x)) {
					yy = y;
					for ( ; yy <= n; yy += (yy & -yy)) update(root[x][yy], 1, m, tx + ty + q[i].len);
				}
			}
			else {
				if (t == 1) {
					x = q[i].x, y = q[i].y;
				}
				else if (t == 2) {
					x = q[i].x, y = n - q[i].y + 1;
				}
				else if (t == 3) {
					x = n - q[i].x + 1, y = q[i].y;
				}
				else {
					x = n - q[i].x + 1, y = n - q[i].y + 1;
				}
				int tx = x, ty = y;
				for ( ; x; x -= (x & -x)) {
					yy = y;
					for ( ; yy; yy -= (yy & -yy)) {
						ans[i] += calc(root[x][yy], 1, m, tx + ty, m);
					}
				}
			}
		}
	}
	for (int i = 0; i < Q; i++) {
		if (q[i].type == 2) printf("%d\n",ans[i]);
	}
}


#include <bits/stdc++.h>
using namespace std;
#define M 5010
#define N 20000010

int root[M][M], ans[100010];

int L[N], R[N], tot, s[N], m;

void update(int &id, int l, int r, int x) {

	if (!id) id = ++tot;

	if (l == r) {
		s[id]++; return;
	}

	int mid = (l + r) >> 1;

	if (x <= mid) update(L[id], l, mid, x);
	else update(R[id], mid + 1, r, x);

	s[id] = s[L[id]] + s[R[id]];

}

int calc(int id, int st, int en, int l, int r) {
	if (!id) return 0;
	if (l <= st && en <= r) return s[id];

	int mid = (st + en) >> 1;
	int res = 0;
	if (l <= mid) res += calc(L[id], st, mid, l, r);
	if (mid < r) res += calc(R[id], mid + 1, en, l, r);
	return res;
}

int n, Q;

struct dat {
	int type, dir, x, y, len;
	dat(int type = 0, int dir = 0, int x = 0, int y = 0, int len = 0) : type(type), dir(dir), x(x), y(y), len(len) {}
} q[100010];

int get(int t, int &x, int &y) {
	if (t == 2) y = n - y + 1;
	else if (t == 3) x = n - x + 1;
	else if (t == 4) {x = n - x + 1; y = n - y + 1;}
}

int main() {
    freopen("III.in", "r", stdin);
    freopen("III_.out", "w", stdout);
	scanf("%d %d", &n, &Q);

	int dir, x, y, t, len, xx, yy;

	for (int i = 0; i < Q; i++) {
		scanf("%d", &t);
		if (t == 1) {
			scanf("%d %d %d %d", &dir, &x, &y, &len);
			q[i] = dat(t, dir, x, y, len);
			get(dir, x, y); m = max(m, x + y + len);
		}
		else {
			scanf("%d %d", &x, &y);
			q[i] = dat(t, 0, x, y);
		}
	}
	for (int t = 1; t <= 4; t++) {
		if (t > 1) {
			memset(root, 0, sizeof(root));
			for (int i = 0; i <= tot; i++) L[i] = R[i] = s[i] = 0;
			tot = 0;
		}
		for (int i = 0; i < Q; i++) {
			if (q[i].type == 1) {
				if (t != q[i].dir) continue;

				x = q[i].x, y = q[i].y;
				get(t, x, y);

				int tx = x, ty = y;
				for ( ; x <= n; x += (x & -x)) {
					yy = y;
					for ( ; yy <= n; yy += (yy & -yy)) update(root[x][yy], 1, m, tx + ty + q[i].len);
				}
			}
			else {

				x = q[i].x, y = q[i].y;
				get(t, x, y);

				int tx = x, ty = y;
				if (tx + ty <= m) {
					for ( ; x; x -= (x & -x)) {
						yy = y;
						for ( ; yy; yy -= (yy & -yy)) {
							ans[i] += calc(root[x][yy], 1, m, tx + ty, m);
						}
					}
				}
			}
		}
	}
	for (int i = 0; i < Q; i++) {
		if (q[i].type == 2) printf("%d\n",ans[i]);
	}
}


#include <bits/stdc++.h>
using namespace std;
#define M 5010
#define N 20000010

int root[M][M << 1], ans[100010];

int L[N], R[N], tot, s[N], m;

void update(int &id, int l, int r, int x) {
	if (!id) id = ++tot;
	if (l == r) {
		s[id]++; return;
	}
	int mid = (l + r) >> 1;

	if (x <= mid) update(L[id], l, mid, x);
	else update(R[id], mid + 1, r, x);

	s[id] = s[L[id]] + s[R[id]];
}

int calc(int id, int st, int en, int l, int r) {
	if (!id) return 0;
	if (l <= st && en <= r) return s[id];
	int mid = (st + en) >> 1;
	int res = 0;
	if (l <= mid) res += calc(L[id], st, mid, l, r);
	if (mid < r) res += calc(R[id], mid + 1, en, l, r);
	return res;
}

int n, Q;

struct dat {
	int type, dir, x, y, len;
	dat(int type = 0, int dir = 0, int x = 0, int y = 0, int len = 0) : type(type), dir(dir), x(x), y(y), len(len) {}
} q[100010];

int get(int t, int &x, int &y) {
	if (t == 2) y = n - y + 1;
	else if (t == 3) x = n - x + 1;
	else if (t == 4) {x = n - x + 1; y = n - y + 1;}
}

int main() {
	scanf("%d %d", &n, &Q);

	int dir, x, y, t, len, xx, yy, S = n + n;

	for (int i = 0; i < Q; i++) {
		scanf("%d", &t);
		if (t == 1) {
			scanf("%d %d %d %d", &dir, &x, &y, &len);
			q[i] = dat(t, dir, x, y, len);
		}
		else {
			scanf("%d %d", &x, &y);
			q[i] = dat(t, 0, x, y);
		}
	}
	m = n << 1;
	for (int t = 1; t <= 4; t++) {
		if (t > 1) {
			memset(root, 0, sizeof(root));
			for (int i = 0; i <= tot; i++) L[i] = R[i] = s[i] = 0;
			tot = 0;
		}
		for (int i = 0; i < Q; i++) {
			if (q[i].type == 1) {
				if (t != q[i].dir) continue;

				x = q[i].x, y = q[i].y;
				get(t, x, y);
				int ty = y + x + q[i].len;
				for ( ; x <= n; x += (x & -x)) {
					yy = ty;
					for ( ; yy; yy -= (yy & -yy)) update(root[x][yy], 1, n, y);
				}
			}
			else {
				x = q[i].x, y = q[i].y;
				get(t, x, y);
				int tx = x, ty = y + x;

                for ( ; x; x -= (x & -x)) {
                    yy = ty;
                    for ( ; yy <= m; yy += (yy & -yy)) {
                        ans[i] += calc(root[x][yy], 1, n, 1, y);
                    }
                }
			}
		}
	}
	for (int i = 0; i < Q; i++) {
		if (q[i].type == 2) printf("%d\n",ans[i]);
	}
}


#include <bits/stdc++.h>
using namespace std;
#define M 5010
#define N 20000010

int root[M][M << 1], ans[100010];

int L[N], R[N], tot, s[N], m;

void update(int &id, int l, int r, int x) {
	if (!id) id = ++tot;
	if (l == r) {
		s[id]++; return;
	}
	int mid = (l + r) >> 1;

	if (x <= mid) update(L[id], l, mid, x);
	else update(R[id], mid + 1, r, x);

	s[id] = s[L[id]] + s[R[id]];

}

int calc(int id, int st, int en, int l, int r) {
	if (!id) return 0;
	if (l <= st && en <= r) return s[id];

	int mid = (st + en) >> 1;
	int res = 0;
	if (l <= mid) res += calc(L[id], st, mid, l, r);
	if (mid < r) res += calc(R[id], mid + 1, en, l, r);
	return res;
}

int n, Q;

struct dat {
	int type, dir, x, y, len;
	dat(int type = 0, int dir = 0, int x = 0, int y = 0, int len = 0) : type(type), dir(dir), x(x), y(y), len(len) {}
} q[100010];

int get(int t, int &x, int &y) {
	if (t == 2) y = n - y + 1;
	else if (t == 3) x = n - x + 1;
	else if (t == 4) {x = n - x + 1; y = n - y + 1;}
}

int main() {
	scanf("%d %d", &n, &Q);

	int dir, x, y, t, len, xx, yy, S = n + n;

	for (int i = 0; i < Q; i++) {
		scanf("%d", &t);
		if (t == 1) {
			scanf("%d %d %d %d", &dir, &x, &y, &len);
			q[i] = dat(t, dir, x, y, len);
			get(dir, x, y);
		}
		else {
			scanf("%d %d", &x, &y);
			q[i] = dat(t, 0, x, y);
		}
	}
	m = n << 1;
	for (int t = 1; t <= 4; t++) {
		if (t > 1) {
			memset(root, 0, sizeof(root));
			for (int i = 0; i <= tot; i++) L[i] = R[i] = s[i] = 0;
			tot = 0;
		}
		for (int i = 0; i < Q; i++) {
			if (q[i].type == 1) {
				if (t != q[i].dir) continue;

				x = q[i].x, y = q[i].y;
				get(t, x, y);

				int tx = x, ty = y + x + q[i].len;
				for ( ; x <= n; x += (x & -x)) {
					yy = ty;
					for ( ; yy; yy -= (yy & -yy)) update(root[x][yy], 1, n, y);
				}
			}
			else {

				x = q[i].x, y = q[i].y;
				get(t, x, y);
				int tx = x, ty = y + x;

                for ( ; x; x -= (x & -x)) {
                    yy = y;
                    for ( ; yy <= m; yy += (yy & -yy)) {
                        ans[i] += calc(root[x][yy], 1, n, 1, y);
                    }
                }
			}
		}
	}
	for (int i = 0; i < Q; i++) {
		if (q[i].type == 2) printf("%d\n",ans[i]);
	}
}


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

int ans[100010];
int n, Q;

struct dat {
	int type, dir, x, y, len;
	dat(int type = 0, int dir = 0, int x = 0, int y = 0, int len = 0) : type(type), dir(dir), x(x), y(y), len(len) {}
} q[100010];

int get(int t, int &x, int &y) {
	if (t == 2) y = n - y + 1;
	else if (t == 3) x = n - x + 1;
	else if (t == 4) {x = n - x + 1; y = n - y + 1;}
}

int f[M][M], g[M][M << 1], sz;

template <typename T>
void update(T a, int x, int y, int v) {
	for ( ; x; x -= (x & -x)) {
		int yy = y;
		for ( ; yy; yy -= (yy & -yy)) a[x][yy] += v;
	}
}

template <typename T>
int calc(T a, int x, int y, int n) {
	int res = 0;
	if (!x || !y) return 0;
	for ( ; x <= sz; x += (x & -x)) {
		int yy = y;
		for ( ; yy <= n; yy += (yy & -yy)) res += a[x][yy];
	}
	return res;
}

int main() {
	scanf("%d %d", &n, &Q);
	sz = n;
	int dir, x, y, t, len, xx, yy;
	for (int i = 0; i < Q; i++) {
		scanf("%d", &t);
		if (t == 1) {
			scanf("%d %d %d %d", &dir, &x, &y, &len);
			q[i] = dat(t, dir, x, y, len);
		}
		else {
			scanf("%d %d", &x, &y);
			q[i] = dat(t, 0, x, y);
		}
	}
	for (int t = 1; t <= 4; t++) {
		if (t > 1) {
			memset(f, 0, sizeof(f));
			memset(g, 0, sizeof(g));
		}
		for (int i = 0; i < Q; i++) {
			if (q[i].type == 1) {
				if (t != q[i].dir) continue;
				x = q[i].x, y = q[i].y, len = q[i].len;
				get(t, x, y);
				update(f, x + len, y - 1, -1);
				update(f, x - 1, y - 1, 1);
				update(g, x + len, x + y + len, 1);
				update(g, x - 1, x + y + len, -1);
			}
			else {
				x = q[i].x, y = q[i].y;
				get(t, x, y);
				ans[i] += (calc(f, x, y, n) + calc(g, x, x + y, 2 * n));
			}
		}
	}
	for (int i = 0; i < Q; i++) {
		if (q[i].type == 2) printf("%d\n",ans[i]);
	}
}


#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#include <deque>
#include <cstring>
#include <functional>
#include <climits>
#include <list>
#include <ctime>

#define F1(x,y,z) for(int x=y;x<z;x++)
#define F2(x,y,z) for(int x=y;x<=z;x++)
#define F3(x,y,z) for(int x=y;x>z;x--)
#define F4(x,y,z) for(int x=y;x>=z;x--)
#define pb push_back
#define LL long long

#define MAX 10005
#define AMAX 16384
#define MOD 1000000007

#define f(c,d) ((1<<(c))*(d))

using namespace std;

struct wa{
	int v;
	int child[2];
} wat;

struct wb{
	vector<wa> v;
	int child[2];
} wbt;

int n,q,ta,tb,tc,td,add,mo,ya,yb;
vector<wb> x[3];

void f2(vector<wa>& v,int a,int b,int c,int d,int e){
	//printf("f2 %d %d %d %d %d\n",a,b,c,d,e);
	if(b==d&&c==e){
		//printf("F2 %d %d %d %d\n",a,add,b,c);
		v[a].v+=add;
		return;
	}
	int bc=(b+c)/2;
	if(d<bc){
		if(v[a].child[0]==0){
			v[a].child[0]=v.size();
			v.pb(wat);
		}
		f2(v,v[a].child[0],b,bc,d,min(e,bc));
	}
	if(e>bc){
		if(v[a].child[1]==0){
			v[a].child[1]=v.size();
			v.pb(wat);
		}
		f2(v,v[a].child[1],bc,c,max(d,bc),e);
	}
}

void f1(int a,int b,int c,int d,int e){
	//printf("f1 %d %d %d %d %d\n",a,b,c,d,e);
	if(b==d&&c==e){
		//printf("F1 %d %d %d %d\n",mo,a,b,c);
		f2(x[mo][a].v,0,0,1<<14,ya,yb);
		return;
	}
	int bc=(b+c)/2;
	if(d<bc){
		if(x[mo][a].child[0]==0){
			x[mo][a].child[0]=x[mo].size();
			x[mo].pb(wbt);
		}
		f1(x[mo][a].child[0],b,bc,d,min(e,bc));
	}
	if(e>bc){
		if(x[mo][a].child[1]==0){
			x[mo][a].child[1]=x[mo].size();
			x[mo].pb(wbt);
		}
		f1(x[mo][a].child[1],bc,c,max(d,bc),e);
	}
}

void f4(vector<wa>& v,int a,int b,int c){
	tc+=v[a].v;
	//if(v[a].v!=0)printf("f4 %d %d %d %d\n",a,b,c,v[a].v);
	int bc=(b+c)/2;
	if(ya<bc){
		if(v[a].child[0])f4(v,v[a].child[0],b,bc);
	}else{
		if(v[a].child[1])f4(v,v[a].child[1],bc,c);
	}
}

void f3(int a,int b,int c){
	//printf("f3 %d %d %d %d\n",mo,a,b,c);
	f4(x[mo][a].v,0,0,1<<14);
	int bc=(b+c)/2;
	if(ta<bc){
		if(x[mo][a].child[0])f3(x[mo][a].child[0],b,bc);
	}else{
		if(x[mo][a].child[1])f3(x[mo][a].child[1],bc,c);
	}
}

int main(){
	wbt.v.pb(wat);
	F1(a,0,3)x[a].pb(wbt);
	scanf("%d",&n);
	yb=n*2+2;
	scanf("%d",&q);
	while(q--){
		scanf("%d",&ta);
		if(ta==1){
			scanf("%d%d%d%d",&ta,&tb,&tc,&td);
			add=ta&1?1:-1;
			mo=0;
			ya=ta&1?tc:tc+1;
			if(ta<3)f1(0,0,1<<14,tb,tb+td+1);
			else f1(0,0,1<<14,tb-td,tb+1);
			add*=-1;
			mo=abs(5-ta*2)==1?1:2;
			if(ta==1)ya=tc+td+1+tb;
			else if(ta==2)ya=tc-td-tb+n;
			else if(ta==3)ya=tc+td+1-tb+n;
			else ya=tc-td+tb;
			if(ta<3)f1(0,0,1<<14,tb,tb+td+1);
			else f1(0,0,1<<14,tb-td,tb+1);
		}else{
			scanf("%d%d",&ta,&tb);
			tc=0;
			mo=0;
			ya=tb;
			f3(0,0,1<<14);
			mo=1;
			ya=tb-ta+n;
			f3(0,0,1<<14);
			mo=2;
			ya=tb+ta;
			f3(0,0,1<<14);
			printf("%d\n",tc);
		}
	}
	//system("pause");
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define n   100005
#define For(i,a,b)  for(int i=a;i<=b;i++)

int     N,Q,T[4],C[n],Ans[n];
struct  Nod{int k,x,y,z;}A[n],B[n],G[4][n];

#define CH  (ch=getchar())
int     IN(){
        int x=0,ch;
        for (;CH<'0'||ch>'9';);
        for (;ch>='0'&&ch<='9';CH)  (x*=10)+=ch-'0';
        return  x;
}

inline  bool    Cmpz(int a,int b)   {return a<b;}
void    Work3(int l,int r)  {
        if  (l>=r)  return; int Mid=l+r>>1,t=0;
        For(i,l,Mid)    if  (!B[i].k)   C[++t]=B[i].z;
        sort(C+1,C+t+1,Cmpz);
        For(i,Mid+1,r)  if  (B[i].k)    Ans[B[i].k]+=upper_bound(C+1,C+t+1,B[i].z)-C-1;
        Work3(l,Mid);   Work3(Mid+1,r);
}

inline  bool    Cmpy(const Nod&a,const Nod&b)   {return a.y<b.y||a.y==b.y&&a.k<b.k;}
void    Work2(int l,int r){
        if  (l>=r)  return; int Mid=l+r>>1,t=0;
        For(i,l,Mid)    if  (!A[i].k)   B[++t]=A[i];
        For(i,Mid+1,r)  if  (A[i].k)    B[++t]=A[i];
        sort(B+1,B+t+1,Cmpy);   Work3(1,t);
        Work2(l,Mid);   Work2(Mid+1,r);
}

inline  bool    Cmpx(const Nod&a,const Nod&b)   {return a.x<b.x||a.x==b.x&&a.k<b.k;}
void    Work1(int k,int l,int r){
        if  (l>=r)  return; int Mid=l+r>>1,t=0;
        For(i,l,Mid)    if  (!G[k][i].k)A[++t]=G[k][i];
        For(i,Mid+1,r)  if  (G[k][i].k) A[++t]=G[k][i];
        sort(A+1,A+t+1,Cmpx);   Work2(1,t);
        Work1(k,l,Mid); Work1(k,Mid+1,r);
}

int     main(){
        N=IN(); Q=IN();
        For(i,1,Q){
            int k=IN();
            if  (k==1)  {
                int d=IN(),x=IN(),y=IN(),l=IN();
                if  (d==1)  G[0][++T[0]]=(Nod){0,x,y,-x-y-l};
                if  (d==2)  G[1][++T[1]]=(Nod){0,x,-y,y-x-l};
                if  (d==3)  G[2][++T[2]]=(Nod){0,-x,y,x-y-l};
                if  (d==4)  G[3][++T[3]]=(Nod){0,-x,-y,x+y-l};    Ans[i]=-1;
            }   else    {
                int x=IN(),y=IN();
                G[0][++T[0]]=(Nod){i,x,y,-x-y};
                G[1][++T[1]]=(Nod){i,x,-y,y-x};
                G[2][++T[2]]=(Nod){i,-x,y,x-y};
                G[3][++T[3]]=(Nod){i,-x,-y,x+y};
            }
        }
        For(i,0,3)  Work1(i,1,T[i]);
        For(i,1,Q)  if  (Ans[i]!=-1)    printf("%d\n",Ans[i]);
}


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define n   100005
#define For(i,a,b)  for(int i=a;i<=b;i++)

int     N,Q,T[4],C[n],Ans[n];
struct  Nod{int k,x,y,z,ID;}A[n],B[n],G[4][n];

#define CH  (ch=getchar())
int     IN(){
        int x=0,ch;
        for (;CH<'0'||ch>'9';);
        for (;ch>='0'&&ch<='9';CH)  (x*=10)+=ch-'0';
        return  x;
}

bool    Cmpz(int a,int b)   {return a<b;}
void    Work3(int l,int r)  {
        if  (l>=r)  return; int Mid=l+r>>1,t=0;
        For(i,l,Mid)    if  (!B[i].k)   C[++t]=B[i].z;
        sort(C+1,C+t+1,Cmpz);
        For(i,Mid+1,r)  if  (B[i].k)    Ans[B[i].ID]+=upper_bound(C+1,C+t+1,B[i].z)-C-1;
        Work3(l,Mid);   Work3(Mid+1,r);
}

bool    Cmpy(const Nod&a,const Nod&b)   {return a.y<b.y||a.y==b.y&&a.k<b.k;}
void    Work2(int l,int r){
        if  (l>=r)  return; int Mid=l+r>>1,t=0;
        For(i,l,Mid)    if  (!A[i].k)   B[++t]=A[i];
        For(i,Mid+1,r)  if  (A[i].k)    B[++t]=A[i];
        sort(B+1,B+t+1,Cmpy);   Work3(1,t);
        Work2(l,Mid);   Work2(Mid+1,r);
}

bool    Cmpx(const Nod&a,const Nod&b)   {return a.x<b.x||a.x==b.x&&a.k<b.k;}
void    Work1(int k,int l,int r){
        if  (l>=r)  return; int Mid=l+r>>1,t=0;
        For(i,l,Mid)    if  (!G[k][i].k)A[++t]=G[k][i];
        For(i,Mid+1,r)  if  (G[k][i].k) A[++t]=G[k][i];
        sort(A+1,A+t+1,Cmpx);   Work2(1,t);
        Work1(k,l,Mid); Work1(k,Mid+1,r);
}

int     main(){
        N=IN(); Q=IN();
        For(i,1,Q){
            int k=IN();
            if  (k==1)  {
                int d=IN(),x=IN(),y=IN(),l=IN();
                if  (d==1)  G[0][++T[0]]=(Nod){0,x,y,-x-y-l,0};
                if  (d==2)  G[1][++T[1]]=(Nod){0,x,-y,y-x-l,0};
                if  (d==3)  G[2][++T[2]]=(Nod){0,-x,y,x-y-l,0};
                if  (d==4)  G[3][++T[3]]=(Nod){0,-x,-y,x+y-l,0};    Ans[i]=-1;
            }   else    {
                int x=IN(),y=IN();
                G[0][++T[0]]=(Nod){1,x,y,-x-y,i};
                G[1][++T[1]]=(Nod){1,x,-y,y-x,i};
                G[2][++T[2]]=(Nod){1,-x,y,x-y,i};
                G[3][++T[3]]=(Nod){1,-x,-y,x+y,i};
            }
        }
        For(i,0,3)  Work1(i,1,T[i]);
        For(i,1,Q)  if  (Ans[i]!=-1)    printf("%d\n",Ans[i]);
}


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=400005,N=5005*2;
int n,Q;
int type,dir,x,y,len;
int c[N];
int q[8],p[M],u[8][M],v[8][M],id[8][M],ans[M];
bool query[M];

void add(int d,int x,int y,int z)
{
	int &m=q[d];
	u[d][m]=x,v[d][m]=y,id[d][m]=z;
	++m;
}
void ins(int i,int dir,int x,int y,int len)
{
	if (dir&1) y=n+1-y;
	if (dir&2) x=n+1-x;
	if (len<0){
		add(dir,x,y,i);
		add(dir+4,x,x+y,i);
	}else{
		add(dir,x-1,y-1,-1);
		add(dir,x+len,y-1,-3);
		add(dir+4,x-1,x+y+len,-3);
		add(dir+4,x+len,x+y+len,-1);
	}
}
void add(int x,int val)
{
	for (;x<=N;x+=x&-x) c[x]+=val;
}
int get(int x)
{
	int val=0;
	for (;x>0;x-=x&-x) val+=c[x];
	return val;
}

int *U,*V,*ID;
bool cmp(const int i,const int j)
{
	return U[i]==U[j]?V[i]==V[j]?ID[i]<ID[j]:V[i]>V[j]:U[i]>U[j];
}
void solve(int l,int r,int *u,int *v,int *id)
{
	int m=(l+r)/2; if (l+1>=r) return;
	solve(l,m,u,v,id),solve(m,r,u,v,id);
	//printf("%d %d\n",l,r);
	inplace_merge(p+l,p+m,p+r,cmp);
	//for (int i=l;i<r;++i)  printf("%d ",p[i]); puts("");
	for (int i=l;i<r;++i){
		int x=p[i];
		//printf("m=%d x=%d %d\n",m,x,v[x]);
		if (x<m && id[x]<0) add(N+1-v[x],id[x]+2);
		if (x>=m && id[x]>=0){
			ans[id[x]] += get(N+1-v[x]);
			//printf("!  %d\n",get(N+1-v[x]));
		}
	}
	for (int i=l;i<r;++i){
		int x=p[i];
		if (x<m && id[x]<0) add(N+1-v[x],-(id[x]+2));
	}
}
int main()
{
	scanf("%d%d",&n,&Q);
	for (int i=0;i<Q;++i){
		scanf("%d",&type);
		if (type == 1){
			scanf("%d%d%d%d",&dir,&x,&y,&len);
			ins(i,dir-1,x,y,len);
		}else{
			scanf("%d%d",&x,&y);
			if (x<=0 || x>n || y<=0 || y>n) for(;;);
			query[i]=1;
			for (int j=0;j<4;++j) ins(i,j,x,y,-1);
		}
	}
	for (int j=0;j<8;++j){
		//printf("j=%d\n",j);
		//for (int i=0;i<q[j];++i){
		//	printf("%d %d %d\n",u[j][i],v[j][i],id[j][i]);
		//}
		memset(c,0,sizeof(c));
		for (int i=0;i<q[j];++i) p[i]=i;
		U=u[j],V=v[j],ID=id[j];
		solve(0,q[j],U,V,ID);
	}
	for (int i=0;i<Q;++i) if (query[i])
		printf("%d\n",ans[i]);
}


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=400005,N=5005*3;
int n,Q;
int type,dir,x,y,len;
int c[N];
int q[8],p[M],u[8][M],v[8][M],id[8][M],ans[M];
bool query[M];

void add(int d,int x,int y,int z)
{
	int &m=q[d];
	u[d][m]=x,v[d][m]=y,id[d][m]=z;
	++m;
}
void ins(int i,int dir,int x,int y,int len)
{
	if (dir&1) y=n+1-y;
	if (dir&2) x=n+1-x;
	if (len<0){
		add(dir,x,y,i);
		add(dir+4,x,x+y,i);
	}else{
		add(dir,x-1,y-1,-1);
		add(dir,x+len,y-1,-3);
		add(dir+4,x-1,x+y+len,-3);
		add(dir+4,x+len,x+y+len,-1);
	}
}
void add(int x,int val)
{
	for (;x<=N;x+=x&-x) c[x]+=val;
}
int get(int x)
{
	int val=0;
	for (;x>0;x-=x&-x) val+=c[x];
	return val;
}

int *U,*V,*ID;
bool cmp(const int i,const int j)
{
	return U[i]==U[j]?V[i]==V[j]?ID[i]<ID[j]:V[i]>V[j]:U[i]>U[j];
}
void solve(int l,int r,int *u,int *v,int *id)
{
	int m=(l+r)/2; if (l+1>=r) return;
	solve(l,m,u,v,id),solve(m,r,u,v,id);
	//printf("%d %d\n",l,r);
	inplace_merge(p+l,p+m,p+r,cmp);
	//for (int i=l;i<r;++i)  printf("%d ",p[i]); puts("");
	for (int i=l;i<r;++i){
		int x=p[i];
		//printf("m=%d x=%d %d\n",m,x,v[x]);
		if (x<m && id[x]<0) add(N+1-v[x],id[x]+2);
		if (x>=m && id[x]>=0){
			ans[id[x]] += get(N+1-v[x]);
			//printf("!  %d\n",get(N+1-v[x]));
		}
	}
	for (int i=l;i<r;++i){
		int x=p[i];
		if (x<m && id[x]<0) add(N+1-v[x],-(id[x]+2));
	}
}
int main()
{
	scanf("%d%d",&n,&Q);
	for (int i=0;i<Q;++i){
		scanf("%d",&type);
		if (type == 1){
			scanf("%d%d%d%d",&dir,&x,&y,&len);
			ins(i,dir-1,x,y,len);
		}else{
			scanf("%d%d",&x,&y);
			//if (x<=0 || x>n || y<=0 || y>n) for(;;);
			query[i]=1;
			for (int j=0;j<4;++j) ins(i,j,x,y,-1);
		}
	}
	for (int j=0;j<8;++j){
		//printf("j=%d\n",j);
		//for (int i=0;i<q[j];++i){
		//	printf("%d %d %d\n",u[j][i],v[j][i],id[j][i]);
		//}
		memset(c,0,sizeof(c));
		for (int i=0;i<q[j];++i) p[i]=i;
		U=u[j],V=v[j],ID=id[j];
		solve(0,q[j],U,V,ID);
	}
	for (int i=0;i<Q;++i) if (query[i])
		printf("%d\n",ans[i]);
}


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=200005,N=5005*2;
int n,Q;
int type,dir,x,y,len;
int c[N];
int q[8],p[M],u[8][M],v[8][M],id[8][M],ans[M];
bool query[M];

void add(int d,int x,int y,int z)
{
	int &m=q[d];
	u[d][m]=x,v[d][m]=y,id[d][m]=z;
	++m;
}
void ins(int i,int dir,int x,int y,int len)
{
	if (dir&1) y=n+1-y;
	if (dir&2) x=n+1-x;
	if (len<0){
		add(dir,x,y,i);
		add(dir+4,x,x+y,i);
	}else{
		add(dir,x-1,y-1,-1);
		add(dir,x+len,y-1,-3);
		add(dir+4,x-1,x+y+len,-3);
		add(dir+4,x+len,x+y+len,-1);
	}
}
void add(int x,int val)
{
	for (;x<=N;x+=x&-x) c[x]+=val;
}
int get(int x)
{
	int val=0;
	for (;x>0;x-=x&-x) val+=c[x];
	return val;
}

int *U,*V,*ID;
bool cmp(const int i,const int j)
{
	return U[i]==U[j]?V[i]==V[j]?ID[i]<ID[j]:V[i]>V[j]:U[i]>U[j];
}
void solve(int l,int r,int *u,int *v,int *id)
{
	int m=(l+r)/2; if (l+1>=r) return;
	solve(l,m,u,v,id),solve(m,r,u,v,id);
	//printf("%d %d\n",l,r);
	inplace_merge(p+l,p+m,p+r,cmp);
	//for (int i=l;i<r;++i)  printf("%d ",p[i]); puts("");
	for (int i=l;i<r;++i){
		int x=p[i];
		//printf("m=%d x=%d %d\n",m,x,v[x]);
		if (x<m && id[x]<0) add(N+1-v[x],id[x]+2);
		if (x>=m && id[x]>=0){
			ans[id[x]] += get(N+1-v[x]);
			//printf("!  %d\n",get(N+1-v[x]));
		}
	}
	for (int i=l;i<r;++i){
		int x=p[i];
		if (x<m && id[x]<0) add(N+1-v[x],-(id[x]+2));
	}
}
int main()
{
	scanf("%d%d",&n,&Q);
	for (int i=0;i<Q;++i){
		scanf("%d",&type);
		if (type == 1){
			scanf("%d%d%d%d",&dir,&x,&y,&len);
			ins(i,dir-1,x,y,len);
		}else{
			scanf("%d%d",&x,&y);
			query[i]=1;
			for (int j=0;j<4;++j) ins(i,j,x,y,-1);
		}
	}
	for (int j=0;j<8;++j){
		//printf("j=%d\n",j);
		//for (int i=0;i<q[j];++i){
		//	printf("%d %d %d\n",u[j][i],v[j][i],id[j][i]);
		//}
		memset(c,0,sizeof(c));
		for (int i=0;i<q[j];++i) p[i]=i;
		U=u[j],V=v[j],ID=id[j];
		solve(0,q[j],U,V,ID);
	}
	for (int i=0;i<Q;++i) if (query[i])
		printf("%d\n",ans[i]);
}


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=400005,N=5005*2;
int n,Q;
int type,dir,x,y,len;
int c[N];
int q[8],p[M],u[8][M],v[8][M],id[8][M],ans[M];
bool query[M];

void add(int d,int x,int y,int z)
{
	int &m=q[d];
	u[d][m]=x,v[d][m]=y,id[d][m]=z;
	++m;
}
void ins(int i,int dir,int x,int y,int len)
{
	if (dir&1) y=n+1-y;
	if (dir&2) x=n+1-x;
	if (len<0){
		add(dir,x,y,i);
		add(dir+4,x,x+y,i);
	}else{
		add(dir,x-1,y-1,-1);
		add(dir,x+len,y-1,-3);
		add(dir+4,x-1,x+y+len,-3);
		add(dir+4,x+len,x+y+len,-1);
	}
}
void add(int x,int val)
{
	for (;x<=N;x+=x&-x) c[x]+=val;
}
int get(int x)
{
	int val=0;
	for (;x>0;x-=x&-x) val+=c[x];
	return val;
}

int *U,*V,*ID;
bool cmp(const int i,const int j)
{
	return U[i]==U[j]?V[i]==V[j]?ID[i]<ID[j]:V[i]>V[j]:U[i]>U[j];
}
void solve(int l,int r,int *u,int *v,int *id)
{
	int m=(l+r)/2; if (l+1>=r) return;
	solve(l,m,u,v,id),solve(m,r,u,v,id);
	//printf("%d %d\n",l,r);
	inplace_merge(p+l,p+m,p+r,cmp);
	//for (int i=l;i<r;++i)  printf("%d ",p[i]); puts("");
	for (int i=l;i<r;++i){
		int x=p[i];
		//printf("m=%d x=%d %d\n",m,x,v[x]);
		if (x<m && id[x]<0) add(N+1-v[x],id[x]+2);
		if (x>=m && id[x]>=0){
			ans[id[x]] += get(N+1-v[x]);
			//printf("!  %d\n",get(N+1-v[x]));
		}
	}
	for (int i=l;i<r;++i){
		int x=p[i];
		if (x<m && id[x]<0) add(N+1-v[x],-(id[x]+2));
	}
}
int main()
{
	scanf("%d%d",&n,&Q);
	for (int i=0;i<Q;++i){
		scanf("%d",&type);
		if (type == 1){
			scanf("%d%d%d%d",&dir,&x,&y,&len);
			ins(i,dir-1,x,y,len);
		}else{
			scanf("%d%d",&x,&y);
			query[i]=1;
			for (int j=0;j<4;++j) ins(i,j,x,y,-1);
		}
	}
	for (int j=0;j<8;++j){
		//printf("j=%d\n",j);
		//for (int i=0;i<q[j];++i){
		//	printf("%d %d %d\n",u[j][i],v[j][i],id[j][i]);
		//}
		memset(c,0,sizeof(c));
		for (int i=0;i<q[j];++i) p[i]=i;
		U=u[j],V=v[j],ID=id[j];
		solve(0,q[j],U,V,ID);
	}
	for (int i=0;i<Q;++i) if (query[i])
		printf("%d\n",ans[i]);
}


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=400005,N=5005*3;
int n,Q;
int type,dir,x,y,len;
int c[N];
int q[8],p[M],u[8][M],v[8][M],id[8][M],ans[M];
bool query[M];

void add(int d,int x,int y,int z)
{
	int &m=q[d];
	u[d][m]=x,v[d][m]=y,id[d][m]=z;
	++m;
}
void ins(int i,int dir,int x,int y,int len)
{
	if (dir&1) y=n+1-y;
	if (dir&2) x=n+1-x;
	if (len<0){
		add(dir,x,y,i);
		add(dir+4,x,x+y,i);
	}else{
		add(dir,x-1,y-1,-1);
		add(dir,x+len,y-1,-3);
		add(dir+4,x-1,x+y+len,-3);
		add(dir+4,x+len,x+y+len,-1);
	}
}
void add(int x,int val)
{
	for (;x<=N;x+=x&-x) c[x]+=val;
}
int get(int x)
{
	int val=0;
	for (;x>0;x-=x&-x) val+=c[x];
	return val;
}

int *U,*V,*ID;
bool cmp(const int i,const int j)
{
	return U[i]==U[j]?V[i]==V[j]?ID[i]<ID[j]:V[i]>V[j]:U[i]>U[j];
}
void solve(int l,int r,int *u,int *v,int *id)
{
	int m=(l+r)/2; if (l+1>=r) return;
	solve(l,m,u,v,id),solve(m,r,u,v,id);
	//printf("%d %d\n",l,r);
	inplace_merge(p+l,p+m,p+r,cmp);
	//for (int i=l;i<r;++i)  printf("%d ",p[i]); puts("");
	for (int i=l;i<r;++i){
		int x=p[i];
		//printf("m=%d x=%d %d\n",m,x,v[x]);
		if (x<m && id[x]<0) add(N-1-v[x],id[x]+2);
		if (x>=m && id[x]>=0){
			ans[id[x]] += get(N-1-v[x]);
			//printf("!  %d\n",get(N+1-v[x]));
		}
	}
	for (int i=l;i<r;++i){
		int x=p[i];
		if (x<m && id[x]<0) add(N-1-v[x],-(id[x]+2));
	}
}
int main()
{
	scanf("%d%d",&n,&Q);
	for (int i=0;i<Q;++i){
		scanf("%d",&type);
		if (type == 1){
			scanf("%d%d%d%d",&dir,&x,&y,&len);
			ins(i,dir-1,x,y,len);
		}else{
			scanf("%d%d",&x,&y);
			//if (x<=0 || x>n || y<=0 || y>n) for(;;);
			query[i]=1;
			for (int j=0;j<4;++j) ins(i,j,x,y,-1);
		}
	}
	for (int j=0;j<8;++j){
		//printf("j=%d\n",j);
		//for (int i=0;i<q[j];++i){
		//	printf("%d %d %d\n",u[j][i],v[j][i],id[j][i]);
		//}
		memset(c,0,sizeof(c));
		memset(p,0,sizeof(p));
		for (int i=0;i<q[j];++i) p[i]=i;
		U=u[j],V=v[j],ID=id[j];
		solve(0,q[j],U,V,ID);
	}
	for (int i=0;i<Q;++i) if (query[i])
		printf("%d\n",ans[i]);
}


#include <cstdio>
#include <cstring>

void it_add(int n, int it[], int p, int v) {
    for (int i = p; i <= n; i += (i & (-i))) {
        it[i] += v;
    }
}

int it_get(int it[], int p) {
    int res = 0;
    for (int i = p; i > 0; i -= (i & (-i))) {
        res += it[i];
    }
    return res;
}

void it2_add(int n, int m, int it[][5020], int p, int l, int r) {
    for (int i = p; i <= n; i += (i & (-i))) {
        it_add(m, it[i], l, 1);
        it_add(m, it[i], r + 1, -1);
    }
}

int it2_get(int it[][5020], int x, int y) {
    int res = 0;
    for (int i = x; i > 0; i -= (i & (-i))) {
        res += it_get(it[i], y);
    }
    return res;
}

int fl[5020][5020];
int di[10020][5020];

int ans[1 << 17];

int n, q;
int tp[1 << 17], x[1 << 17], y[1 << 17], len[1 << 17], dir[1 << 17];

int rt[] = {0, 1, 3, 2};

void ncor(int d, int ox, int oy, int &nx, int &ny) {
    --d;
    nx = ox;
    ny = oy;
    for (int i = 0; i < rt[d]; ++i) {
        int x, y;
        x = -ny;
        y = nx;

        nx = x + n + 1;
        ny = y;
    }
}

int main() {
    scanf("%d %d", &n, &q);
    for (int i = 0; i < q; ++i) {
        scanf("%d", &tp[i]);
        if (tp[i] == 1) {
            scanf("%d %d %d %d", &dir[i], &x[i], &y[i], &len[i]);
        } else {
            scanf("%d %d", &x[i], &y[i]);
        }
    }

    memset(ans, 0, sizeof(ans));
    for (int dr = 1; dr <= 4; ++dr) {
        memset(fl, 0, sizeof(fl));
        memset(di, 0, sizeof(di));
        for (int i = 0; i < q; ++i) {
            int nx, ny;
            ncor(dr, x[i], y[i], nx, ny);
            if (tp[i] == 1 && dir[i] == dr) {
                it2_add(n, n, fl, nx, ny, ny + len[i]);
                it2_add(n + n, n, di, nx + ny + len[i], ny, ny + len[i]);
            } else {
                ans[i] += it2_get(fl, nx, ny) - it2_get(di, nx + ny - 1, ny);
            }
        }
    }
    for (int i = 0; i < q; ++i) {
        if (tp[i] == 2) {
            printf("%d\n", ans[i]);
        }
    }
    return 0;
}


#include <iostream>

using namespace std;

const int MAXN = 5005;
int a[MAXN][MAXN], fen[MAXN][MAXN];

void add(int x, int y, int val) {
    int yy = y;
    for(; x < MAXN; x |= x + 1) {
        y = yy;
        for(; y < MAXN; y |= y + 1)
            fen[x][y] += val;
    }
}

int get(int x, int y) {
    int res = 0, yy = y;
    for(; x >= 0; x = (x & (x + 1)) - 1) {
        y = yy;
        for(; y >= 0; y = (y & (y + 1)) - 1)
            res += fen[x][y];
    }
    return res;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, q;
    cin >> n >> q;
    for(int qq = 0; qq < q; qq++) {
        int qt;
        cin >> qt;
        if(qt == 1) {
            int dir, x, y, len;
            cin >> dir >> x >> y >> len;
            x--;
            y--;
            if(dir == 1) {
                add(x, y, 1);
                add(x + len + 1, y, -1);
                for(int i = x; i <= x + len; i++)
                    a[i][y + len - (i - x) + 1]--;
            }
            else if(dir == 2) {
                add(x, y + 1, -1);
                add(x + len + 1, y + 1, 1);
                for(int i = x; i <= x + len; i++)
                    a[i][y - len + (i - x)]++;
            }
            else if(dir == 3) {
                add(x - len, y, 1);
                add(x + 1, y, -1);
                for(int i = x - len; i <= x; i++)
                    a[i][y + len - (x - i) + 1]--;
            }
            else {
                add(x - len, y + 1, -1);
                add(x + 1, y + 1, 1);
                for(int i = x - len; i <= x; i++)
                    a[i][y - len + (x - i)]++;
            }
        }
        else {
            int x, y;
            cin >> x >> y;
            x--;
            y--;
            int ans = get(x, y);
            for(int i = 0; i <= y; i++)
                ans += a[x][i];
            cout << ans << '\n';
        }
    }
    return 0;
}


#include <iostream>

using namespace std;

const int MAXN = 5005;
int *fen[3][MAXN];

void add(int t, int x, int y, int val) {
    int yy = y;
    for(; x < MAXN; x |= x + 1) {
        y = yy;
        for(; y < MAXN; y |= y + 1)
            fen[t][x][y] += val;
    }
}

int get(int t, int x, int y) {
    int res = 0, yy = y;
    for(; x >= 0; x = (x & (x + 1)) - 1) {
        y = yy;
        for(; y >= 0; y = (y & (y + 1)) - 1)
            res += fen[t][x][y];
    }
    return res;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    for(int i = 0; i < MAXN; i++)
        fen[0][i] = new int[MAXN];
    for(int i = 0; i < MAXN; i++)
        fen[1][i] = new int[2 * MAXN];
    for(int i = 0; i < MAXN; i++)
        fen[2][i] = new int[2 * MAXN];
    int n, q;
    cin >> n >> q;
    for(int qq = 0; qq < q; qq++) {
        int qt;
        cin >> qt;
        if(qt == 1) {
            int dir, x, y, len;
            cin >> dir >> x >> y >> len;
            x--;
            y--;
            if(dir == 1) {
                add(0, x, y, 1);
                add(0, x + len + 1, y, -1);
                add(1, x, x + y + len + 1, -1);
                add(1, x + len + 1, x + y + len + 1, 1);
            }
            else if(dir == 2) {
                add(0, x, y + 1, -1);
                add(0, x + len + 1, y + 1, 1);
                add(2, x, y + n - x - 1 - len, 1);
                add(2, x + len + 1, y + n - x - 1 - len, -1);
            }
            else if(dir == 3) {
                add(0, x - len, y, 1);
                add(0, x + 1, y, -1);
                add(2, x - len, y + n - x + len, -1);
                add(2, x + 1, y + n - x + len, 1);
            }
            else {
                add(0, x - len, y + 1, -1);
                add(0, x + 1, y + 1, 1);
                add(1, x - len, x + y - len, 1);
                add(1, x + 1, x + y - len, -1);
            }
        }
        else {
            int x, y;
            cin >> x >> y;
            x--;
            y--;
            cout << get(0, x, y) + get(1, x, x + y) + get(2, x, y + n - x - 1)
                 << '\n';
        }
    }
    return 0;
}


#include <iostream>

using namespace std;

const int MAXN = 5005;
int a[MAXN][MAXN];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, q;
    cin >> n >> q;
    for(int qq = 0; qq < q; qq++) {
        int qt;
        cin >> qt;
        if(qt == 1) {
            int dir, x, y, len;
            cin >> dir >> x >> y >> len;
            x--;
            y--;
            if(dir == 1)
                for(int i = x, h = y + len + 1; i <= x + len; i++, h--) {
                    a[i][y]++;
                    a[i][h]--;
                }
            else if(dir == 2) {
                y++;
                for(int i = x, h = y - len - 1; i <= x + len; i++, h++) {
                    a[i][h]++;
                    a[i][y]--;
                }
            }
            else if(dir == 3)
                for(int i = x - len, h = y + 1; i <= x; i++, h++) {
                    a[i][y]++;
                    a[i][h]--;
                }
            else {
                y++;
                for(int i = x - len, h = y - 1; i <= x; i++, h--) {
                    a[i][h]++;
                    a[i][y]--;
                }
            }
        }
        else {
            int x, y;
            cin >> x >> y;
            x--;
            y--;
            int ans = 0;
            for(int i = 0; i <= y; i++)
                ans += a[x][i];
            cout << ans << '\n';
        }
    }
    return 0;
}


#include <iostream>

using namespace std;

const int MAXN = 5005;
int a[MAXN][MAXN];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, q;
    cin >> n >> q;
    for(int qq = 0; qq < q; qq++) {
        int qt;
        cin >> qt;
        if(qt == 1) {
            int dir, x, y, len;
            cin >> dir >> x >> y >> len;
            x--;
            y--;
            if(dir == 1)
                for(int i = x; i <= x + len; i++) {
                    a[i][y]++;
                    a[i][y + len - (i - x) + 1]--;
                }
            else if(dir == 2)
                for(int i = x; i <= x + len; i++) {
                    a[i][y - len + (i - x)]++;
                    a[i][y + 1]--;
                }
            else if(dir == 3)
                for(int i = x - len; i <= x; i++) {
                    a[i][y]++;
                    a[i][y + len - (x - i) + 1]--;
                }
            else
                for(int i = x - len; i <= x; i++) {
                    a[i][y - len + (x - i)]++;
                    a[i][y + 1]--;
                }
        }
        else {
            int x, y;
            cin >> x >> y;
            x--;
            y--;
            int ans = 0;
            for(int i = 0; i <= y; i++)
                ans += a[x][i];
            cout << ans << '\n';
        }
    }
    return 0;
}


#include <iostream>

using namespace std;

const int MAXN = 5005;
int *fen[3][MAXN], sz[] = {MAXN, 2 * MAXN, 2 * MAXN};

void add(int t, int x, int y, int val) {
    int yy = y;
    for(; x < MAXN; x |= x + 1) {
        y = yy;
        for(; y < sz[t]; y |= y + 1)
            fen[t][x][y] += val;
    }
}

int get(int t, int x, int y) {
    int res = 0, yy = y;
    for(; x >= 0; x = (x & (x + 1)) - 1) {
        y = yy;
        for(; y >= 0; y = (y & (y + 1)) - 1)
            res += fen[t][x][y];
    }
    return res;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    for(int i = 0; i < MAXN; i++)
        fen[0][i] = new int[MAXN]();
    for(int i = 0; i < MAXN; i++)
        fen[1][i] = new int[2 * MAXN]();
    for(int i = 0; i < MAXN; i++)
        fen[2][i] = new int[2 * MAXN]();
    int n, q;
    cin >> n >> q;
    for(int qq = 0; qq < q; qq++) {
        int qt;
        cin >> qt;
        if(qt == 1) {
            int dir, x, y, len;
            cin >> dir >> x >> y >> len;
            x--;
            y--;
            if(dir == 1) {
                add(0, x, y, 1);
                add(0, x + len + 1, y, -1);
                add(1, x, x + y + len + 1, -1);
                add(1, x + len + 1, x + y + len + 1, 1);
            }
            else if(dir == 2) {
                add(0, x, y + 1, -1);
                add(0, x + len + 1, y + 1, 1);
                add(2, x, y + n - x - 1 - len, 1);
                add(2, x + len + 1, y + n - x - 1 - len, -1);
            }
            else if(dir == 3) {
                add(0, x - len, y, 1);
                add(0, x + 1, y, -1);
                add(2, x - len, y + n - x + len, -1);
                add(2, x + 1, y + n - x + len, 1);
            }
            else {
                add(0, x - len, y + 1, -1);
                add(0, x + 1, y + 1, 1);
                add(1, x - len, x + y - len, 1);
                add(1, x + 1, x + y - len, -1);
            }
        }
        else {
            int x, y;
            cin >> x >> y;
            x--;
            y--;
            cout << get(0, x, y) + get(1, x, x + y) + get(2, x, y + n - x - 1)
                 << '\n';
        }
    }
    return 0;
}


#include <iostream>

using namespace std;

const int MAXN = 5005;
int *fen[3][MAXN];

void add(int t, int x, int y, int val) {
    int yy = y;
    for(; x < MAXN; x |= x + 1) {
        y = yy;
        for(; y < MAXN; y |= y + 1)
            fen[t][x][y] += val;
    }
}

int get(int t, int x, int y) {
    int res = 0, yy = y;
    for(; x >= 0; x = (x & (x + 1)) - 1) {
        y = yy;
        for(; y >= 0; y = (y & (y + 1)) - 1)
            res += fen[t][x][y];
    }
    return res;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    for(int i = 0; i < MAXN; i++)
        fen[0][i] = new int[MAXN]();
    for(int i = 0; i < MAXN; i++)
        fen[1][i] = new int[2 * MAXN]();
    for(int i = 0; i < MAXN; i++)
        fen[2][i] = new int[2 * MAXN]();
    int n, q;
    cin >> n >> q;
    for(int qq = 0; qq < q; qq++) {
        int qt;
        cin >> qt;
        if(qt == 1) {
            int dir, x, y, len;
            cin >> dir >> x >> y >> len;
            x--;
            y--;
            if(dir == 1) {
                add(0, x, y, 1);
                add(0, x + len + 1, y, -1);
                add(1, x, x + y + len + 1, -1);
                add(1, x + len + 1, x + y + len + 1, 1);
            }
            else if(dir == 2) {
                add(0, x, y + 1, -1);
                add(0, x + len + 1, y + 1, 1);
                add(2, x, y + n - x - 1 - len, 1);
                add(2, x + len + 1, y + n - x - 1 - len, -1);
            }
            else if(dir == 3) {
                add(0, x - len, y, 1);
                add(0, x + 1, y, -1);
                add(2, x - len, y + n - x + len, -1);
                add(2, x + 1, y + n - x + len, 1);
            }
            else {
                add(0, x - len, y + 1, -1);
                add(0, x + 1, y + 1, 1);
                add(1, x - len, x + y - len, 1);
                add(1, x + 1, x + y - len, -1);
            }
        }
        else {
            int x, y;
            cin >> x >> y;
            x--;
            y--;
            cout << get(0, x, y) + get(1, x, x + y) + get(2, x, y + n - x - 1)
                 << '\n';
        }
    }
    return 0;
}


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

typedef unsigned int u32;
#define REP(i, a, b) for (int i = (a); i < (b); ++i)
#define PER(i, a, b) for (int i = (a); i > (b); --i)
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)

inline int read()
{
    static char ch;
    while (ch = getchar(), ch < '0' || ch > '9');
    int res = ch - 48;
    while (ch = getchar(), ch >= '0' && ch <= '9') res = res * 10 + ch - 48;
    return res;
}

inline u32 Rand()
{
    static u32 x = 998666131;
    return x += x << 2 | 1;
}

const int N = 5001, M = 1e5 + 5, T = 2e6;
int n, m, Q, ans[M];
bool vis[M];

struct QueryT
{
    int op, x, y, dir, len, lab;
    inline void Reset1(const int &_op, const int &_dir, const int &_x, const int &_y, const int &_len)
    {
        op = _op;
        dir = _dir;
        x = _x;
        y = _y;
        len = _len;
    }
    inline void Reset2(const int &_op, const int &_dir, const int &_x, const int &_y, const int &_lab)
    {
        op = _op;
        dir = _dir;
        x = _x;
        y = _y;
        lab = _lab;
        len = x + y;
    }
    inline bool operator <= (const QueryT &rhs)
    {
    //    if (x != rhs.x)
            return x < rhs.x;
     //   return op <= rhs.op;
    }
} qry[M * 4], tmp[M * 4];

struct node
{
    node *lc, *rc;
    int val, sze;
    u32 pri;

    inline void Update()
    {
        sze = (lc ? lc->sze : 0) + (rc ? rc->sze : 0) + 1;
    }
} used[T], *pool = used, *unused[T], **top = unused;
node *rt[5][N];

inline node* new_node()
{
    node *res;
    if (top != unused)
        res = *--top;
    else res = pool++;
    res->lc = res->rc = NULL;
    return res;
}

inline void del_node(node *&u)
{
    if (!u) return ;
    del_node(u->lc);
    del_node(u->rc);
    *top++ = u;
    u = NULL;
}

inline void Zig(node *&u)
{
    node *v = u->lc;
    u->lc = v->rc;
    v->rc = u;
    v->sze = u->sze;
    u->Update();
    u = v;
}

inline void Zag(node *&u)
{
    node *v = u->rc;
    u->rc = v->lc;
    v->lc = u;
    v->sze = u->sze;
    u->Update();
    u = v;
}

inline void Insert(node *&u, const int &val)
{
    if (!u)
    {
        u = new_node();
        u->val = val; u->sze = 1;
        u->pri = Rand();
        return ;
    }
    ++u->sze;
    if (val <= u->val)
    {
        Insert(u->lc, val);
        if (u->lc->pri < u->pri)
            Zig(u);
    }
    else
    {
        Insert(u->rc, val);
        if (u->rc->pri < u->pri)
            Zag(u);
    }
}

inline int moreQuery(node *u, const int &val)
{
    if (!u) return 0;
    if (u->val < val)
        return moreQuery(u->rc, val);
    return (u->rc ? u->rc->sze + 1 : 1) + moreQuery(u->lc, val);
}

inline void add(node **R, int x, const int &val)
{
    for (; x <= n; x += x & -x)
        Insert(R[x], val);
}

inline int Query(node **R, int x, const int &val)
{
    int res = 0;
    for (; x > 0; x -= x & -x)
        res += moreQuery(R[x], val);
    return res;
}

inline void Clear(node **R, int x)
{
    for (; x <= n; x += x & -x)
        del_node(R[x]);
}

inline void cdqSolve(const int &l, const int &r)
{
    if (l == r) return ;
    int mid = l + r >> 1;
    cdqSolve(l, mid); cdqSolve(mid + 1, r);

    int ql = l, qr = mid + 1;
    FOR(i, l, r)
    {
        if (qr > r || (ql <= mid && qry[ql] <= qry[qr]))
        {
            tmp[i] = qry[ql++];
            if (tmp[i].op == 1)
                add(rt[tmp[i].dir], tmp[i].y, tmp[i].len);
        }
        else
        {
            tmp[i] = qry[qr++];
            if (tmp[i].op == 2)
                ans[tmp[i].lab] += Query(rt[tmp[i].dir], tmp[i].y, tmp[i].len);
        }
    }
    FOR(i, l, r)
    {
        qry[i] = tmp[i];
        if (qry[i].op == 1)
            Clear(rt[qry[i].dir], qry[i].y);
    }
}

int main()
{
    n = read(); Q = read();

    int op, x, y, len, dir;
    FOR(i, 1, Q)
    {
        op = read();
        if (op == 1)
        {
            dir = read(), x = read(), y = read(), len = read();
            if (dir == 2) y = n - y + 1;
            if (dir == 3) x = n - x + 1;
            if (dir == 4) x = n - x + 1, y = n - y + 1;
            len += x + y;
            qry[++m].Reset1(op, dir, x, y, len);
        }
        else
        {
            x = read(), y = read();
            qry[++m].Reset2(op, 1, x, y, i);
            qry[++m].Reset2(op, 2, x, n - y + 1, i);
            qry[++m].Reset2(op, 3, n - x + 1, y, i);
            qry[++m].Reset2(op, 4, n - x + 1, n - y + 1, i);
            vis[i] = true;
        }
    }

    cdqSolve(1, m);
    FOR(i, 1, Q) if (vis[i])
        printf("%d\n", ans[i]);
    return 0;
}


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

typedef unsigned int u32;
#define REP(i, a, b) for (int i = (a); i < (b); ++i)
#define PER(i, a, b) for (int i = (a); i > (b); --i)
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)

inline int read()
{
    static char ch;
    while (ch = getchar(), ch < '0' || ch > '9');
    int res = ch - 48;
    while (ch = getchar(), ch >= '0' && ch <= '9') res = res * 10 + ch - 48;
    return res;
}

inline u32 Rand()
{
    static u32 x = 998666131;
    return x += x << 2 | 1;
}

const int N = 5001, M = 1e5 + 5, T = 2e6;
int n, m, Q, ans[M];
bool vis[M];

struct QueryT
{
    int op, x, y, dir, len, lab;
    inline void Reset1(const int &_op, const int &_dir, const int &_x, const int &_y, const int &_len)
    {
        op = _op;
        dir = _dir;
        x = _x;
        y = _y;
        len = _len;
    }
    inline void Reset2(const int &_op, const int &_dir, const int &_x, const int &_y, const int &_lab)
    {
        op = _op;
        dir = _dir;
        x = _x;
        y = _y;
        lab = _lab;
        len = x + y;
    }
    inline bool operator <= (const QueryT &rhs)
    {
        if (x != rhs.x)
            return x < rhs.x;
        return op < rhs.op;
    }
} qry[M * 4], tmp[M * 4];

struct node
{
    node *lc, *rc;
    int val, sze;
    u32 pri;

    inline void Update()
    {
        sze = (lc ? lc->sze : 0) + (rc ? rc->sze : 0) + 1;
    }
} used[T], *pool = used;
node *rt[5][N];

inline node* new_node()
{
    node *res = pool++;
    res->lc = res->rc = NULL;
    return res;
}

inline void Zig(node *&u)
{
    node *v = u->lc;
    u->lc = v->rc;
    v->rc = u;
    v->sze = u->sze;
    u->Update();
    u = v;
}

inline void Zag(node *&u)
{
    node *v = u->rc;
    u->rc = v->lc;
    v->lc = u;
    v->sze = u->sze;
    u->Update();
    u = v;
}

inline void Insert(node *&u, const int &val)
{
    if (!u)
    {
        u = new_node();
        u->val = val; u->sze = 1;
        u->pri = Rand();
        return ;
    }
    ++u->sze;
    if (val <= u->val)
    {
        Insert(u->lc, val);
        if (u->lc->pri < u->pri)
            Zig(u);
    }
    else
    {
        Insert(u->rc, val);
        if (u->rc->pri < u->pri)
            Zag(u);
    }
}

inline int moreQuery(node *u, const int &val)
{
    if (!u) return 0;
    if (u->val < val)
        return moreQuery(u->rc, val);
    return (u->rc ? u->rc->sze + 1 : 1) + moreQuery(u->lc, val);
}

inline void add(node **R, int x, const int &val)
{
    for (; x <= n; x += x & -x)
        Insert(R[x], val);
}

inline int Query(node **R, int x, const int &val)
{
    int res = 0;
    for (; x > 0; x -= x & -x)
        res += moreQuery(R[x], val);
    return res;
}

inline void Clear(node **R, int x)
{
    for (; x <= n && R[x]; x += x & -x)
		R[x] = NULL;
}

inline void cdqSolve(const int &l, const int &r)
{
    if (l == r) return ;
    int mid = l + r >> 1;
    cdqSolve(l, mid); cdqSolve(mid + 1, r);

    int ql = l, qr = mid + 1;
    FOR(i, l, r)
    {
        if (qr > r || (ql <= mid && qry[ql] <= qry[qr]))
        {
            tmp[i] = qry[ql++];
            if (tmp[i].op == 1)
                add(rt[tmp[i].dir], tmp[i].y, tmp[i].len);
        }
        else
        {
            tmp[i] = qry[qr++];
            if (tmp[i].op == 2)
                ans[tmp[i].lab] += Query(rt[tmp[i].dir], tmp[i].y, tmp[i].len);
        }
    }
    FOR(i, l, r)
    {
        qry[i] = tmp[i];
        if (qry[i].op == 1)
            Clear(rt[qry[i].dir], qry[i].y);
    }
	pool = used;
}

int main()
{
    n = read(); Q = read();

    int op, x, y, len, dir;
    FOR(i, 1, Q)
    {
        op = read();
        if (op == 1)
        {
            dir = read(), x = read(), y = read(), len = read();
            if (dir == 2) y = n - y + 1;
            if (dir == 3) x = n - x + 1;
            if (dir == 4) x = n - x + 1, y = n - y + 1;
            len += x + y;
            qry[++m].Reset1(op, dir, x, y, len);
        }
        else
        {
            x = read(), y = read();
            qry[++m].Reset2(op, 1, x, y, i);
            qry[++m].Reset2(op, 2, x, n - y + 1, i);
            qry[++m].Reset2(op, 3, n - x + 1, y, i);
            qry[++m].Reset2(op, 4, n - x + 1, n - y + 1, i);
            vis[i] = true;
        }
    }

    cdqSolve(1, m);
    FOR(i, 1, Q) if (vis[i])
        printf("%d\n", ans[i]);
    return 0;
}


#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;

typedef unsigned u32;

inline u32 myrand()
{
	static u32 x = 998244353;
	return x += x << 2 | 1;
}

inline int getint()
{
	static char c;
	while ((c = getchar()) < '0' || c > '9');

	int res = c - '0';
	while ((c = getchar()) >= '0' && c <= '9')
		res = res * 10 + c - '0';
	return res;
}

const int NDir = 4;
const int MaxN = 5001;
const int MaxQ = 100001;
const int MaxM = 400001;
const int MaxLogM = 19;
const int MaxTN = MaxM * MaxLogM >> 2;

int n, nQu, m = 0, nQuery = 0;
int ans[MaxQ];

struct operation
{
	int type, lab;
	int x, y, dir;

	friend inline bool operator<(const operation &lhs, const operation &rhs)
	{
		if (lhs.x != rhs.x)
			return lhs.x < rhs.x;
		return lhs.type <= rhs.type;
	}

	inline void set(const int &t, const int &l, const int &_x, const int &_y, const int &d)
	{
		type = t, lab = l;
		x = _x, y = _y, dir = d;
	}
};
operation q[MaxM], p[MaxM];

struct treap_node
{
	treap_node *lc, *rc;
	int val, size;
	u32 pri;

	inline void update()
	{
		size = 1;
		if (lc)
			size += lc->size;
		if (rc)
			size += rc->size;
	}
};
treap_node pool[MaxTN], *tail = pool;

inline treap_node *newnode()
{
	treap_node *x = tail++;
	x->lc = x->rc = NULL;
	x->pri = myrand(), x->size = 1;
	return x;
}

inline void treap_zig(treap_node *&x)
{
	treap_node *y = x->lc;
	x->lc = y->rc;
	y->rc = x;
	x->update();
	x = y;
}
inline void treap_zag(treap_node *&x)
{
	treap_node *y = x->rc;
	x->rc = y->lc;
	y->lc = x;
	x->update();
	x = y;
}

void treap_insert(treap_node *&x, const int &val)
{
	if (x == NULL)
	{
		x = newnode(), x->val = val;
		return;
	}

	if (val <= x->val)
	{
		treap_insert(x->lc, val);
		if (x->pri < x->lc->pri)
			treap_zig(x);
	}
	else
	{
		treap_insert(x->rc, val);
		if (x->pri < x->rc->pri)
			treap_zag(x);
	}
	x->update();
}

inline int treap_query(treap_node *x, const int &val)
{
	int rank = 0;
	while (x)
	{
		if (val > x->val)
			x = x->rc;
		else
		{
			int r = x->rc ? x->rc->size : 0;
			rank += r + 1;
			x = x->lc;
		}
	}
	return rank;
}

treap_node *bit[NDir][MaxN];

inline void bit_update(treap_node **b, const int &x, const int &val)
{
	for (int i = x; i <= n; i += i & -i)
		treap_insert(b[i], val);
}
inline int bit_query(treap_node **b, const int &x, const int &val)
{
	int res = 0;
	for (int i = x; i; i ^= i & -i)
		res += treap_query(b[i], val);
	return res;
}
inline void bit_reinit(treap_node **b, const int &x)
{
	for (int i = x; i <= n && b[i]; i += i & -i)
		b[i] = NULL;
}

void solve(const int &l, const int &r)
{
	if (l == r)
		return;
	int mid = l + r >> 1;
	solve(l, mid);
	solve(mid + 1, r);

	int i = l, j = mid + 1;
	for (int t = l; t <= r; ++t)
	{
		if (j > r || (i <= mid && q[i] < q[j]))
		{
			p[t] = q[i++];
			if (p[t].type == 0)
				bit_update(bit[p[t].dir], p[t].y, p[t].lab);
		}
		else
		{
			p[t] = q[j++];
			if (p[t].type == 1)
			{
				int len = p[t].x + p[t].y;
				ans[p[t].lab] += bit_query(bit[p[t].dir], p[t].y, len);
			}
		}
	}

	tail = pool;
	for (i = l; i <= r; ++i)
	{
		q[i] = p[i];
		if (q[i].type == 0)
			bit_reinit(bit[q[i].dir], q[i].y);
	}
}

int main()
{
	n = getint(), nQu = getint();
	while (nQu--)
	{
		int type = getint();
		if (type == 1)
		{
			int dir = getint();
			int x = getint(), y = getint(), l = getint();
			if (dir == 2 || dir == 4)
				y = n - y + 1;
			if (dir == 3 || dir == 4)
				x = n - x + 1;
			q[++m].set(0, l + x + y, x, y, --dir);
		}
		else
		{
			int x = getint(), y = getint();
			q[++m].set(1, ++nQuery, x, y, 0);
			q[++m].set(1, nQuery, x, n - y + 1, 1);
			q[++m].set(1, nQuery, n - x + 1, y, 2);
			q[++m].set(1, nQuery, n - x + 1, n - y + 1, 3);
		}
	}

	solve(1, m);

	for (int i = 1; i <= nQuery; ++i)
		printf("%d\n", ans[i]);

	return 0;
}


#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;

typedef unsigned u32;

inline u32 myrand()
{
	static u32 x = 998244353;
	return x += x << 2 | 1;
}

inline int getint()
{
	static char c;
	while ((c = getchar()) < '0' || c > '9');

	int res = c - '0';
	while ((c = getchar()) >= '0' && c <= '9')
		res = res * 10 + c - '0';
	return res;
}

const int NDir = 4;
const int MaxN = 5001;
const int MaxQ = 100001;
const int MaxM = 400001;
const int MaxLogM = 19;
const int MaxTN = MaxM * MaxLogM >> 2;

int n, nQu, m = 0, nQuery = 0;
int ans[MaxQ];

struct operation
{
	int type, lab;
	int x, y, dir;

	friend inline bool operator<(const operation &lhs, const operation &rhs)
	{
		if (lhs.x != rhs.x)
			return lhs.x < rhs.x;
		return lhs.type <= rhs.type;
	}

	inline void set(const int &t, const int &l, const int &_x, const int &_y, const int &d)
	{
		type = t, lab = l;
		x = _x, y = _y, dir = d;
	}
};
operation q[MaxM], p[MaxM];

struct treap_node
{
	treap_node *lc, *rc;
	int val, size;
	u32 pri;

	inline void update()
	{
		size = 0;
		if (lc)
			size += lc->size;
		if (rc)
			size += rc->size;
	}
};
treap_node pool[MaxTN], *tail = pool;

inline treap_node *newnode() // orz myh
{
	treap_node *x = tail++;
	x->lc = x->rc = NULL;
	x->pri = myrand(), x->size = 1;
	return x;
}

inline void treap_zig(treap_node *&x)
{
	treap_node *y = x->lc;
	x->lc = y->rc;
	y->rc = x;
	x->update();
	x = y;
}
inline void treap_zag(treap_node *&x)
{
	treap_node *y = x->rc;
	x->rc = y->lc;
	y->lc = x;
	x->update();
	x = y;
}

void treap_insert(treap_node *&x, const int &val)
{
	if (x == NULL)
	{
		x = newnode(), x->val = val;
		return;
	}

	++x->size;
	if (val <= x->val)
	{
		treap_insert(x->lc, val);
		if (x->pri < x->lc->pri)
			treap_zig(x);
	}
	else
	{
		treap_insert(x->rc, val);
		if (x->pri < x->rc->pri)
			treap_zag(x);
	}
}

inline int treap_query(treap_node *x, const int &val)
{
	int rank = 0;
	while (x)
	{
		if (val > x->val)
			x = x->rc;
		else
		{
			int r = x->rc ? x->rc->size : 0;
			rank += r + 1;
			x = x->lc;
		}
	}
	return rank;
}

treap_node *bit[NDir][MaxN];

inline void bit_update(treap_node **b, const int &x, const int &val)
{
	for (int i = x; i <= n; i += i & -i)
		treap_insert(b[i], val);
}
inline int bit_query(treap_node **b, const int &x, const int &val)
{
	int res = 0;
	for (int i = x; i; i ^= i & -i)
		res += treap_query(b[i], val);
	return res;
}
inline void bit_reinit(treap_node **b, const int &x)
{
	for (int i = x; i <= n && b[i]; i += i & -i)
		b[i] = NULL;
}

void solve(const int &l, const int &r)
{
	if (l == r)
		return;
	int mid = l + r >> 1;
	solve(l, mid);
	solve(mid + 1, r);

	int i = l, j = mid + 1;
	for (int t = l; t <= r; ++t)
	{
		if (j > r || (i <= mid && q[i] < q[j]))
		{
			p[t] = q[i++];
			if (p[t].type == 0)
				bit_update(bit[p[t].dir], p[t].x, p[t].lab);
		}
		else
		{
			p[t] = q[j++];
			if (p[t].type == 1)
			{
				int len = p[t].x + p[t].y;
				ans[p[t].lab] += bit_query(bit[p[t].dir], p[t].x, len);
			}
		}
	}

	tail = pool;
	for (i = l; i <= r; ++i)
	{
		q[i] = p[i];
		if (q[i].type == 0)
			bit_reinit(bit[q[i].dir], q[i].x);
	}
}

int main()
{
	n = getint(), nQu = getint();
	while (nQu--)
	{
		int type = getint();
		if (type == 1)
		{
			int dir = getint() - 1;
			int x = getint(), y = getint(), l = getint();
			if (dir == 1 || dir == 3)
				y = n - y + 1;
			if (dir == 2 || dir == 3)
				x = n - x + 1;
			q[++m].set(0, l + x + y, x, y, dir);
		}
		else
		{
			int x = getint(), y = getint();
			q[++m].set(1, ++nQuery, x, y, 0);
			q[++m].set(1, nQuery, x, n - y + 1, 1);
			q[++m].set(1, nQuery, n - x + 1, y, 2);
			q[++m].set(1, nQuery, n - x + 1, n - y + 1, 3);
		}
	}

	solve(1, m);

	for (int i = 1; i <= nQuery; ++i)
		printf("%d\n", ans[i]);

	return 0;
}


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

typedef unsigned int u32;
#define REP(i, a, b) for (int i = (a); i < (b); ++i)
#define PER(i, a, b) for (int i = (a); i > (b); --i)
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)

inline int read()
{
    static char ch;
    while (ch = getchar(), ch < '0' || ch > '9');
    int res = ch - 48;
    while (ch = getchar(), ch >= '0' && ch <= '9') res = res * 10 + ch - 48;
    return res;
}

inline u32 Rand()
{
    static u32 x = 998666131;
    return x += x << 2 | 1;
}

const int N = 5001, M = 1e5 + 5, T = 2e6;
int n, m, Q, ans[M];
bool vis[M];

struct QueryT
{
    int op, x, y, dir, len, lab;
    inline void Reset1(const int &_op, const int &_dir, const int &_x, const int &_y, const int &_len)
    {
        op = _op;
        dir = _dir;
        x = _x;
        y = _y;
        len = _len;
    }
    inline void Reset2(const int &_op, const int &_dir, const int &_x, const int &_y, const int &_lab)
    {
        op = _op;
        dir = _dir;
        x = _x;
        y = _y;
        lab = _lab;
        len = x + y;
    }
    inline bool operator <= (const QueryT &rhs)
    {
        if (x != rhs.x)
            return x < rhs.x;
        return op <= rhs.op;
    }
} qry[M * 4], tmp[M * 4];

struct node
{
    node *lc, *rc;
    int val, sze;
    u32 pri;

    inline void Update()
    {
        sze = (lc ? lc->sze : 0) + (rc ? rc->sze : 0) + 1;
    }
} used[T], *pool = used, *unused[T], **top = unused;
node *rt[5][N];

inline node* new_node()
{
    node *res;
    if (top != unused)
        res = *--top;
    else res = pool++;
    res->lc = res->rc = NULL;
    return res;
}

inline void del_node(node *&u)
{
    if (!u) return ;
    del_node(u->lc);
    del_node(u->rc);
    *top++ = u;
    u = NULL;
}

inline void Zig(node *&u)
{
    node *v = u->lc;
    u->lc = v->rc;
    v->rc = u;
    v->sze = u->sze;
    u->Update();
    u = v;
}

inline void Zag(node *&u)
{
    node *v = u->rc;
    u->rc = v->lc;
    v->lc = u;
    v->sze = u->sze;
    u->Update();
    u = v;
}

inline void Insert(node *&u, const int &val)
{
    if (!u)
    {
        u = new_node();
        u->val = val; u->sze = 1;
        u->pri = Rand();
        return ;
    }
    ++u->sze;
    if (val <= u->val)
    {
        Insert(u->lc, val);
        if (u->lc->pri < u->pri)
            Zig(u);
    }
    else
    {
        Insert(u->rc, val);
        if (u->rc->pri < u->pri)
            Zag(u);
    }
}

inline int moreQuery(node *u, const int &val)
{
    if (!u) return 0;
    if (u->val < val)
        return moreQuery(u->rc, val);
    return (u->rc ? u->rc->sze + 1 : 1) + moreQuery(u->lc, val);
}

inline void add(node **R, int x, const int &val)
{
    for (; x <= n; x += x & -x)
        Insert(R[x], val);
}

inline int Query(node **R, int x, const int &val)
{
    int res = 0;
    for (; x > 0; x -= x & -x)
        res += moreQuery(R[x], val);
    return res;
}

inline void Clear(node **R, int x)
{
    for (; x <= n && R[x]; x += x & -x)
		R[x] = NULL;
}

inline void cdqSolve(const int &l, const int &r)
{
    if (l == r) return ;
    int mid = l + r >> 1;
    cdqSolve(l, mid); cdqSolve(mid + 1, r);

    int ql = l, qr = mid + 1;
    FOR(i, l, r)
    {
        if (qr > r || (ql <= mid && qry[ql] <= qry[qr]))
        {
            tmp[i] = qry[ql++];
            if (tmp[i].op == 1)
                add(rt[tmp[i].dir], tmp[i].y, tmp[i].len);
        }
        else
        {
            tmp[i] = qry[qr++];
            if (tmp[i].op == 2)
                ans[tmp[i].lab] += Query(rt[tmp[i].dir], tmp[i].y, tmp[i].len);
        }
    }
    FOR(i, l, r)
    {
        qry[i] = tmp[i];
        if (qry[i].op == 1)
            Clear(rt[qry[i].dir], qry[i].y);
    }
	pool = used;
}

int main()
{
    n = read(); Q = read();

    int op, x, y, len, dir;
    FOR(i, 1, Q)
    {
        op = read();
        if (op == 1)
        {
            dir = read(), x = read(), y = read(), len = read();
            if (dir == 2) y = n - y + 1;
            if (dir == 3) x = n - x + 1;
            if (dir == 4) x = n - x + 1, y = n - y + 1;
            len += x + y;
            qry[++m].Reset1(op, dir, x, y, len);
        }
        else
        {
            x = read(), y = read();
            qry[++m].Reset2(op, 1, x, y, i);
            qry[++m].Reset2(op, 2, x, n - y + 1, i);
            qry[++m].Reset2(op, 3, n - x + 1, y, i);
            qry[++m].Reset2(op, 4, n - x + 1, n - y + 1, i);
            vis[i] = true;
        }
    }

    cdqSolve(1, m);
    FOR(i, 1, Q) if (vis[i])
        printf("%d\n", ans[i]);
    return 0;
}


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

typedef unsigned int u32;
#define REP(i, a, b) for (int i = (a); i < (b); ++i)
#define PER(i, a, b) for (int i = (a); i > (b); --i)
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)

inline int read()
{
    static char ch;
    while (ch = getchar(), ch < '0' || ch > '9');
    int res = ch - 48;
    while (ch = getchar(), ch >= '0' && ch <= '9') res = res * 10 + ch - 48;
    return res;
}

inline u32 Rand()
{
    static u32 x = 998666131;
    return x += x << 2 | 1;
}

const int N = 5001, M = 1e5 + 5, T = 2e6;
int n, m, Q, ans[M];
bool vis[M];

struct QueryT
{
    int op, x, y, dir, len, lab;
    inline void Reset1(const int &_op, const int &_dir, const int &_x, const int &_y, const int &_len)
    {
        op = _op;
        dir = _dir;
        x = _x;
        y = _y;
        len = _len;
    }
    inline void Reset2(const int &_op, const int &_dir, const int &_x, const int &_y, const int &_lab)
    {
        op = _op;
        dir = _dir;
        x = _x;
        y = _y;
        lab = _lab;
        len = x + y;
    }
    inline bool operator <= (const QueryT &rhs)
    {
        if (x != rhs.x)
            return x < rhs.x;
        return op < rhs.op;
    }
} qry[M * 4], tmp[M * 4];

struct node
{
    node *lc, *rc;
    int val, sze;
    u32 pri;

    inline void Update()
    {
        sze = (lc ? lc->sze : 0) + (rc ? rc->sze : 0) + 1;
    }
} used[T], *pool = used;
node *rt[5][N];

inline node* new_node()
{
    node *res;
    if (top != unused)
        res = *--top;
    else res = pool++;
    res->lc = res->rc = NULL;
    return res;
}

inline void Zig(node *&u)
{
    node *v = u->lc;
    u->lc = v->rc;
    v->rc = u;
    v->sze = u->sze;
    u->Update();
    u = v;
}

inline void Zag(node *&u)
{
    node *v = u->rc;
    u->rc = v->lc;
    v->lc = u;
    v->sze = u->sze;
    u->Update();
    u = v;
}

inline void Insert(node *&u, const int &val)
{
    if (!u)
    {
        u = new_node();
        u->val = val; u->sze = 1;
        u->pri = Rand();
        return ;
    }
    ++u->sze;
    if (val <= u->val)
    {
        Insert(u->lc, val);
        if (u->lc->pri < u->pri)
            Zig(u);
    }
    else
    {
        Insert(u->rc, val);
        if (u->rc->pri < u->pri)
            Zag(u);
    }
}

inline int moreQuery(node *u, const int &val)
{
    if (!u) return 0;
    if (u->val < val)
        return moreQuery(u->rc, val);
    return (u->rc ? u->rc->sze + 1 : 1) + moreQuery(u->lc, val);
}

inline void add(node **R, int x, const int &val)
{
    for (; x <= n; x += x & -x)
        Insert(R[x], val);
}

inline int Query(node **R, int x, const int &val)
{
    int res = 0;
    for (; x > 0; x -= x & -x)
        res += moreQuery(R[x], val);
    return res;
}

inline void Clear(node **R, int x)
{
    for (; x <= n && R[x]; x += x & -x)
		R[x] = NULL;
}

inline void cdqSolve(const int &l, const int &r)
{
    if (l == r) return ;
    int mid = l + r >> 1;
    cdqSolve(l, mid); cdqSolve(mid + 1, r);

    int ql = l, qr = mid + 1;
    FOR(i, l, r)
    {
        if (qr > r || (ql <= mid && qry[ql] <= qry[qr]))
        {
            tmp[i] = qry[ql++];
            if (tmp[i].op == 1)
                add(rt[tmp[i].dir], tmp[i].y, tmp[i].len);
        }
        else
        {
            tmp[i] = qry[qr++];
            if (tmp[i].op == 2)
                ans[tmp[i].lab] += Query(rt[tmp[i].dir], tmp[i].y, tmp[i].len);
        }
    }
    FOR(i, l, r)
    {
        qry[i] = tmp[i];
        if (qry[i].op == 1)
            Clear(rt[qry[i].dir], qry[i].y);
    }
	pool = used;
}

int main()
{
    n = read(); Q = read();

    int op, x, y, len, dir;
    FOR(i, 1, Q)
    {
        op = read();
        if (op == 1)
        {
            dir = read(), x = read(), y = read(), len = read();
            if (dir == 2) y = n - y + 1;
            if (dir == 3) x = n - x + 1;
            if (dir == 4) x = n - x + 1, y = n - y + 1;
            len += x + y;
            qry[++m].Reset1(op, dir, x, y, len);
        }
        else
        {
            x = read(), y = read();
            qry[++m].Reset2(op, 1, x, y, i);
            qry[++m].Reset2(op, 2, x, n - y + 1, i);
            qry[++m].Reset2(op, 3, n - x + 1, y, i);
            qry[++m].Reset2(op, 4, n - x + 1, n - y + 1, i);
            vis[i] = true;
        }
    }

    cdqSolve(1, m);
    FOR(i, 1, Q) if (vis[i])
        printf("%d\n", ans[i]);
    return 0;
}


#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;

typedef unsigned u32;

inline u32 myrand()
{
	static u32 x = 998244353;
	return x += x << 2 | 1;
}

inline int getint()
{
	static char c;
	while ((c = getchar()) < '0' || c > '9');

	int res = c - '0';
	while ((c = getchar()) >= '0' && c <= '9')
		res = res * 10 + c - '0';
	return res;
}

const int NDir = 4;
const int MaxN = 5001;
const int MaxQ = 100001;
const int MaxM = 400001;
const int MaxLogM = 19;
const int MaxTN = MaxM * MaxLogM >> 2;

int n, nQu, m = 0, nQuery = 0;
int ans[MaxQ];

struct operation
{
	int type, lab;
	int x, y, dir;

	friend inline bool operator<(const operation &lhs, const operation &rhs)
	{
		if (lhs.x != rhs.x)
			return lhs.x < rhs.x;
		return lhs.type <= rhs.type;
	}

	inline void set(const int &t, const int &l, const int &_x, const int &_y, const int &d)
	{
		type = t, lab = l;
		x = _x, y = _y, dir = d;
	}
};
operation q[MaxM], p[MaxM];

struct treap_node
{
	treap_node *lc, *rc;
	int val, size;
	u32 pri;

	inline void update()
	{
		size = 0;
		if (lc)
			size += lc->size;
		if (rc)
			size += rc->size;
	}
};
treap_node pool[MaxTN], *tail = pool;

inline treap_node *newnode() // orz myh
{
	treap_node *x = tail++;
	x->lc = x->rc = NULL;
	x->pri = myrand(), x->size = 1;
	return x;
}

inline void treap_zig(treap_node *&x)
{
	treap_node *y = x->lc;
	x->lc = y->rc;
	y->rc = x;
	x->update();
	x = y;
}
inline void treap_zag(treap_node *&x)
{
	treap_node *y = x->rc;
	x->rc = y->lc;
	y->lc = x;
	x->update();
	x = y;
}

void treap_insert(treap_node *&x, const int &val)
{
	if (x == NULL)
	{
		x = newnode(), x->val = val;
		return;
	}

	++x->size;
	if (val <= x->val)
	{
		treap_insert(x->lc, val);
		if (x->pri < x->lc->pri)
			treap_zig(x);
	}
	else
	{
		treap_insert(x->rc, val);
		if (x->pri < x->rc->pri)
			treap_zag(x);
	}
}

inline int treap_query(treap_node *x, const int &val)
{
	int rank = 0;
	while (x)
	{
		if (val > x->val)
			x = x->rc;
		else
		{
			int r = x->rc ? x->rc->size : 0;
			rank += r + 1;
			x = x->lc;
		}
	}
	return rank;
}

treap_node *bit[NDir][MaxN];

inline void bit_update(treap_node **b, const int &x, const int &val)
{
	for (int i = x; i <= n; i += i & -i)
		treap_insert(b[i], val);
}
inline int bit_query(treap_node **b, const int &x, const int &val)
{
	int res = 0;
	for (int i = x; i; i ^= i & -i)
		res += treap_query(b[i], val);
	return res;
}
inline void bit_reinit(treap_node **b, const int &x)
{
	for (int i = x; i <= n && b[i]; i += i & -i)
		b[i] = NULL;
}

void solve(const int &l, const int &r)
{
	if (l == r)
		return;
	int mid = l + r >> 1;
	solve(l, mid);
	solve(mid + 1, r);

	int i = l, j = mid + 1;
	for (int t = l; t <= r; ++t)
	{
		if (j > r || (i <= mid && q[i] < q[j]))
		{
			p[t] = q[i++];
			if (p[t].type == 0)
				bit_update(bit[p[t].dir], p[t].y, p[t].lab);
		}
		else
		{
			p[t] = q[j++];
			if (p[t].type == 1)
			{
				int len = p[t].x + p[t].y;
				ans[p[t].lab] += bit_query(bit[p[t].dir], p[t].y, len);
			}
		}
	}

	tail = pool;
	for (i = l; i <= r; ++i)
	{
		q[i] = p[i];
		if (q[i].type == 0)
			bit_reinit(bit[q[i].dir], q[i].y);
	}
}

int main()
{
	n = getint(), nQu = getint();
	while (nQu--)
	{
		int type = getint();
		if (type == 1)
		{
			int dir = getint() - 1;
			int x = getint(), y = getint(), l = getint();
			if (dir == 1 || dir == 3)
				y = n - y + 1;
			if (dir == 2 || dir == 3)
				x = n - x + 1;
			q[++m].set(0, l + x + y, x, y, dir);
		}
		else
		{
			int x = getint(), y = getint();
			q[++m].set(1, ++nQuery, x, y, 0);
			q[++m].set(1, nQuery, x, n - y + 1, 1);
			q[++m].set(1, nQuery, n - x + 1, y, 2);
			q[++m].set(1, nQuery, n - x + 1, n - y + 1, 3);
		}
	}

	solve(1, m);

	for (int i = 1; i <= nQuery; ++i)
		printf("%d\n", ans[i]);

	return 0;
}


#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;

typedef unsigned u32;

inline u32 myrand()
{
	static u32 x = 998244353;
	return x += x << 2 | 1;
}

inline int getint()
{
	static char c;
	while ((c = getchar()) < '0' || c > '9');

	int res = c - '0';
	while ((c = getchar()) >= '0' && c <= '9')
		res = res * 10 + c - '0';
	return res;
}

const int NDir = 4;
const int MaxN = 5001;
const int MaxQ = 100001;
const int MaxM = 400001;
const int MaxLogM = 19;
const int MaxTN = MaxM * MaxLogM >> 1;

int n, nQu, m = 0, nQuery = 0;
int ans[MaxQ];

struct operation
{
	int type, lab;
	int x, y, dir;

	friend inline bool operator<(const operation &lhs, const operation &rhs)
	{
		if (lhs.x != rhs.x)
			return lhs.x < rhs.x;
		return lhs.type <= rhs.type;
	}

	inline void set(const int &t, const int &l, const int &_x, const int &_y, const int &d)
	{
		type = t, lab = l;
		x = _x, y = _y, dir = d;
	}
};
operation q[MaxM], p[MaxM];

struct treap_node
{
	treap_node *lc, *rc;
	int val, size;
	u32 pri;

	inline void update()
	{
		size = 1;
		if (lc)
			size += lc->size;
		if (rc)
			size += rc->size;
	}
};
treap_node pool[MaxTN], *tail = pool;

inline treap_node *newnode()
{
	treap_node *x = tail++;
	x->lc = x->rc = NULL;
	x->pri = myrand(), x->size = 1;
	return x;
}

inline void treap_zig(treap_node *&x)
{
	treap_node *y = x->lc;
	x->lc = y->rc;
	y->rc = x;
	x->update();
	x = y;
}
inline void treap_zag(treap_node *&x)
{
	treap_node *y = x->rc;
	x->rc = y->lc;
	y->lc = x;
	x->update();
	x = y;
}

void treap_insert(treap_node *&x, const int &val)
{
	if (x == NULL)
	{
		x = newnode(), x->val = val;
		return;
	}

	++x->size;
	if (val <= x->val)
	{
		treap_insert(x->lc, val);
		if (x->pri < x->lc->pri)
			treap_zig(x);
	}
	else
	{
		treap_insert(x->rc, val);
		if (x->pri < x->rc->pri)
			treap_zag(x);
	}
}

inline int treap_query(treap_node *x, const int &val)
{
	int rank = 0;
	while (x)
	{
		if (val > x->val)
			x = x->rc;
		else
		{
			int r = x->rc ? x->rc->size : 0;
			rank += r + 1;
			x = x->lc;
		}
	}
	return rank;
}

treap_node *bit[NDir][MaxN];

inline void bit_update(treap_node **b, const int &x, const int &val)
{
	for (int i = x; i <= n; i += i & -i)
		treap_insert(b[i], val);
}
inline int bit_query(treap_node **b, const int &x, const int &val)
{
	int res = 0;
	for (int i = x; i; i ^= i & -i)
		res += treap_query(b[i], val);
	return res;
}
inline void bit_reinit(treap_node **b, const int &x)
{
	for (int i = x; i <= n && b[i]; i += i & -i)
		b[i] = NULL;
}

void solve(const int &l, const int &r)
{
	if (l == r)
		return;
	int mid = l + r >> 1;
	solve(l, mid);
	solve(mid + 1, r);

	int i = l, j = mid + 1;
	for (int t = l; t <= r; ++t)
	{
		if (j > r || (i <= mid && q[i] < q[j]))
		{
			p[t] = q[i++];
			if (p[t].type == 0)
				bit_update(bit[p[t].dir], p[t].y, p[t].lab);
		}
		else
		{
			p[t] = q[j++];
			if (p[t].type == 1)
			{
				int len = p[t].x + p[t].y;
				ans[p[t].lab] += bit_query(bit[p[t].dir], p[t].y, len);
			}
		}
	}

	tail = pool;
	for (i = l; i <= r; ++i)
	{
		q[i] = p[i];
		if (q[i].type == 0)
			bit_reinit(bit[q[i].dir], q[i].y);
	}
}

int main()
{
	n = getint(), nQu = getint();
	while (nQu--)
	{
		int type = getint();
		if (type == 1)
		{
			int dir = getint() - 1;
			int x = getint(), y = getint(), l = getint();
			if (dir == 1 || dir == 3)
				y = n - y + 1;
			if (dir == 2 || dir == 3)
				x = n - x + 1;
			q[++m].set(0, l + x + y, x, y, dir);
		}
		else
		{
			int x = getint(), y = getint();
			q[++m].set(1, ++nQuery, x, y, 0);
			q[++m].set(1, nQuery, x, n - y + 1, 1);
			q[++m].set(1, nQuery, n - x + 1, y, 2);
			q[++m].set(1, nQuery, n - x + 1, n - y + 1, 3);
		}
	}

	solve(1, m);

	for (int i = 1; i <= nQuery; ++i)
		printf("%d\n", ans[i]);

	return 0;
}


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

typedef unsigned int u32;
#define REP(i, a, b) for (int i = (a); i < (b); ++i)
#define PER(i, a, b) for (int i = (a); i > (b); --i)
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)

inline int read()
{
    static char ch;
    while (ch = getchar(), ch < '0' || ch > '9');
    int res = ch - 48;
    while (ch = getchar(), ch >= '0' && ch <= '9') res = res * 10 + ch - 48;
    return res;
}

inline u32 Rand()
{
    static u32 x = 998666131;
    return x += x << 2 | 1;
}

const int N = 5001, M = 1e5 + 5, T = 2e6;
int n, m, Q, ans[M];
bool vis[M];

struct QueryT
{
    int op, x, y, dir, len, lab;
    inline void Reset1(const int &_op, const int &_dir, const int &_x, const int &_y, const int &_len)
    {
        op = _op;
        dir = _dir;
        x = _x;
        y = _y;
        len = _len;
    }
    inline void Reset2(const int &_op, const int &_dir, const int &_x, const int &_y, const int &_lab)
    {
        op = _op;
        dir = _dir;
        x = _x;
        y = _y;
        lab = _lab;
        len = x + y;
    }
    inline bool operator <= (const QueryT &rhs)
    {
        if (x != rhs.x)
            return x < rhs.x;
        return op <= rhs.op;
    }
} qry[M * 4], tmp[M * 4];

struct node
{
    node *lc, *rc;
    int val, sze;
    u32 pri;

    inline void Update()
    {
        sze = (lc ? lc->sze : 0) + (rc ? rc->sze : 0) + 1;
    }
} used[T], *pool = used, *unused[T], **top = unused;
node *rt[5][N];

inline node* new_node()
{
    node *res;
    if (top != unused)
        res = *--top;
    else res = pool++;
    res->lc = res->rc = NULL;
    return res;
}

inline void del_node(node *&u)
{
    if (!u) return ;
    del_node(u->lc);
    del_node(u->rc);
    *top++ = u;
    u = NULL;
}

inline void Zig(node *&u)
{
    node *v = u->lc;
    u->lc = v->rc;
    v->rc = u;
    v->sze = u->sze;
    u->Update();
    u = v;
}

inline void Zag(node *&u)
{
    node *v = u->rc;
    u->rc = v->lc;
    v->lc = u;
    v->sze = u->sze;
    u->Update();
    u = v;
}

inline void Insert(node *&u, const int &val)
{
    if (!u)
    {
        u = new_node();
        u->val = val; u->sze = 1;
        u->pri = Rand();
        return ;
    }
    ++u->sze;
    if (val <= u->val)
    {
        Insert(u->lc, val);
        if (u->lc->pri < u->pri)
            Zig(u);
    }
    else
    {
        Insert(u->rc, val);
        if (u->rc->pri < u->pri)
            Zag(u);
    }
}

inline int moreQuery(node *u, const int &val)
{
    if (!u) return 0;
    if (u->val < val)
        return moreQuery(u->rc, val);
    return (u->rc ? u->rc->sze + 1 : 1) + moreQuery(u->lc, val);
}

inline void add(node **R, int x, const int &val)
{
    for (; x <= n; x += x & -x)
        Insert(R[x], val);
}

inline int Query(node **R, int x, const int &val)
{
    int res = 0;
    for (; x > 0; x -= x & -x)
        res += moreQuery(R[x], val);
    return res;
}

inline void Clear(node **R, int x)
{
    for (; x <= n; x += x & -x)
        del_node(R[x]);
}

inline void cdqSolve(const int &l, const int &r)
{
    if (l == r) return ;
    int mid = l + r >> 1;
    cdqSolve(l, mid); cdqSolve(mid + 1, r);

    int ql = l, qr = mid + 1;
    FOR(i, l, r)
    {
        if (qr > r || (ql <= mid && qry[ql] <= qry[qr]))
        {
            tmp[i] = qry[ql++];
            if (tmp[i].op == 1)
                add(rt[tmp[i].dir], tmp[i].y, tmp[i].len);
        }
        else
        {
            tmp[i] = qry[qr++];
            if (tmp[i].op == 2)
                ans[tmp[i].lab] += Query(rt[tmp[i].dir], tmp[i].y, tmp[i].len);
        }
    }
    FOR(i, l, r)
    {
        qry[i] = tmp[i];
        if (qry[i].op == 1)
            Clear(rt[qry[i].dir], qry[i].y);
    }
}

int main()
{
    n = read(); Q = read();

    int op, x, y, len, dir;
    FOR(i, 1, Q)
    {
        op = read();
        if (op == 1)
        {
            dir = read(), x = read(), y = read(), len = read();
            if (dir == 2) y = n - y + 1;
            if (dir == 3) x = n - x + 1;
            if (dir == 4) x = n - x + 1, y = n - y + 1;
            len += x + y;
            qry[++m].Reset1(op, dir, x, y, len);
        }
        else
        {
            x = read(), y = read();
            qry[++m].Reset2(op, 1, x, y, i);
            qry[++m].Reset2(op, 2, x, n - y + 1, i);
            qry[++m].Reset2(op, 3, n - x + 1, y, i);
            qry[++m].Reset2(op, 4, n - x + 1, n - y + 1, i);
            vis[i] = true;
        }
    }

    cdqSolve(1, m);
    FOR(i, 1, Q) if (vis[i])
        printf("%d\n", ans[i]);
    return 0;
}