#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
template<class T> inline void chkmax(T &x, const T &y) { if(x < y) x = y; }
template<class T> inline void chkmin(T &x, const T &y) { if(x > y) x = y; }
const int MAXN = (1 << 20);
const int inf = (int)1e9 + 42;
const int bound = (int)1e9;

struct segment_tree
{
	vector<int> li[4 * MAXN];
	int mx[4 * MAXN];

	void init(int l, int r, int idx)
	{
		if(l == r)
		{
			li[idx].clear();
			mx[idx] = -inf;
			return;
		}

		int mid = (l + r) >> 1;
		init(l, mid, 2 * idx + 1);
		init(mid + 1, r, 2 * idx + 2);

		mx[idx] = max(mx[2 * idx + 1], mx[2 * idx + 2]);
	}

	void add(int pos, int id, int l, int r, int idx)
	{
		if(l > pos || r < pos) return;

		if(l == r && pos == l)
		{
			li[idx].push_back(id);
			mx[idx] = id;
			return;
		}

		int mid = (l + r) >> 1;
		add(pos, id, l, mid, 2 * idx + 1);
		add(pos, id, mid + 1, r, 2 * idx + 2);

		mx[idx] = max(mx[2 * idx + 1], mx[2 * idx + 2]);
	}

	void rem(int pos, int l, int r, int idx)
	{
		if(pos > r || pos < l)
			return;

		if(pos == l && l == r)
		{
			li[idx].pop_back();
			if(li[idx].empty()) mx[idx] = -inf;
			else mx[idx] = li[idx].back();
			return;
		}

		int mid = (l + r) >> 1;
		rem(pos, l, mid, 2 * idx + 1);
		rem(pos, mid + 1, r, 2 * idx + 2);

		mx[idx] = max(mx[2 * idx + 1], mx[2 * idx + 2]);
	}

	int query(int qL, int qR, int l, int r, int idx)
	{
		if(qL > r || qR < l)
			return -inf;

		if(qL <= l && r <= qR)
			return mx[idx];

		int mid = (l + r) >> 1;
		return max(query(qL, qR, l, mid, 2 * idx + 1), query(qL, qR, mid + 1, r, 2 * idx + 2));
	}
};

struct rect
{
	int x1, y1, x2, y2;
};

int n;
rect a[MAXN];

void print_inp()
{
	cout << n << endl;
	for(int i = 0; i < n; i++)
		cout << a[i].x1 << " " << a[i].y1 << " " << a[i].x2 - a[i].x1 << " " << a[i].y2 - a[i].y1 << endl;
	cout << flush;
}

int m;
vector<int> available;
pair<int, pair<int, int> > li_p[MAXN];

void read()
{
	cin >> n >> m;
	for(int i = 0; i < n; i++)
		cin >> a[i].x1 >> a[i].y1 >> a[i].x2 >> a[i].y2;

	for(int i = 0; i < m; i++)
	{
		int x, y, k;
		cin >> x >> y >> k;
		available.push_back(k);
		li_p[i] = {x, {y, k}};
	}

	sort(available.begin(), available.end());
	available.erase(unique(available.begin(), available.end()), available.end());
	for(int i = 0; i < m; i++)
		li_p[i].second.second = lower_bound(available.begin(), available.end(), li_p[i].second.second) - available.begin() + 1;	
}

vector<pair<int, int> > ev;
vector<int> cli;

int get_cord(int x)
{
	return lower_bound(cli.begin(), cli.end(), x) - cli.begin();
}

segment_tree t;
vector<int> G[MAXN];
int answer[MAXN];
set<int> st;
int tr_sz[MAXN];

vector<int> values[MAXN];

void pre_dfs(int u, int pr)
{
	tr_sz[u] = 1;
	for(int v: G[u])
		if(v != pr)
		{
			pre_dfs(v, u);
			tr_sz[u] += tr_sz[v];
		}
}

int cnt[MAXN];
int curr_ans;

void add_vertex(int u)
{
	for(int val: values[u]) 
	{
		cnt[val]++;
		if(cnt[val] == 1)
			curr_ans++;
	}
}

void clear(int u, int pr)
{
	for(int val: values[u]) cnt[val] = 0;
	for(int v: G[u])
		if(v != pr)
			clear(v, u);
}

void add(int u, int pr)
{
	add_vertex(u);
	for(int v: G[u])
		if(v != pr)
			add(v, u);
}

void dfs(int u, int pr, int keep)
{
	pair<int, int> mx = {-1, -1};
	for(int v: G[u])
		if(v != pr)
			mx = max(mx, {tr_sz[v], v});

	for(int v: G[u])
		if(v != pr && v != mx.second)
			dfs(v, u, 0);

	if(mx.second != -1)
		dfs(mx.second, u, 1);

	for(int v: G[u])
		if(v != pr && v != mx.second)
			add(v, u);

	add_vertex(u);
	answer[u] = curr_ans;

	if(keep) return;
	clear(u, pr);
	curr_ans = 0;
}

const int OFFSET = (200000);

bool cmp(pair<int, int> a, pair<int, int> b)
{
	if(a.first != b.first) return a.first < b.first;
	return a.second > b.second;
}

void solve()
{
	for(int i = 0; i < n; i++)
	{
		ev.push_back(make_pair(a[i].x2, i));
		cli.push_back(a[i].y1);
		cli.push_back(a[i].y2);
	}

	for(int i = 0; i < m; i++)
	{
		ev.push_back(make_pair(li_p[i].first, OFFSET + i));
		cli.push_back(li_p[i].second.first);
	}

	sort(ev.begin(), ev.end(), cmp);
	sort(cli.begin(), cli.end());
	cli.erase(unique(cli.begin(), cli.end()), cli.end());
	t.init(0, cli.size(), 0);

	int e_idx = 0;
	for(auto e: ev)
	{
		if(e.second >= OFFSET)
		{
			int i = e.second - OFFSET;
			t.add(get_cord(li_p[i].second.first), e_idx++, 0, cli.size(), 0);
			continue;
		}

		int i = e.second, L = get_cord(a[i].y1) + 1, R = get_cord(a[i].y2) - 1;

		int pos;
		while(((pos = t.query(L - 1, R + 1, 0, cli.size(), 0)) >= 0))
		{
			if(ev[pos].second >= OFFSET) 
			{
				if(li_p[ev[pos].second - OFFSET].first < a[i].x1) break;
				values[i].push_back(li_p[ev[pos].second - OFFSET].second.second);
				t.rem(get_cord(li_p[ev[pos].second - OFFSET].second.first), 0, cli.size(), 0);
				continue;
			}

			if(a[ev[pos].second].x2 < a[i].x1) break;
			G[i].push_back(ev[pos].second);
			t.rem(get_cord(a[ev[pos].second].y1), 0, cli.size(), 0);
		}

		t.add(L - 1, e_idx++, 0, cli.size(), 0);
	}

	int pos;
	while((pos = t.query(0, cli.size(), 0, cli.size(), 0)) >= 0)
	{
		if(ev[pos].second >= OFFSET) 
		{
			t.rem(get_cord(li_p[ev[pos].second - OFFSET].second.first), 0, cli.size(), 0);
			continue;
		}

		G[MAXN - 1].push_back(ev[pos].second);
		t.rem(get_cord(a[ev[pos].second].y1), 0, cli.size(), 0);
	}

	pre_dfs(MAXN - 1, MAXN - 1);
	dfs(MAXN - 1, MAXN - 1, 1);

	for(int i = 0; i < n; i++)
		cout << answer[i] << endl;
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}

