#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e6 + 5;
const int M = 1e6;
const long long INF = (long long)(1e18);
const int inf = 2e9;
const long long MOD = 1000000007LL;
const int START_HORI = 1;
const int VERTI = 2;
const int END_HORI = 3;
struct Event {
  int x;
  int l;
  int r;
  int type;
  bool operator<(const Event& e) const {
    if (this->x != e.x) return this->x < e.x;
    return this->type < e.type;
  }
};
void printEvent(Event e) {
  cout << "X: " << e.x << "\n";
  cout << "L: " << e.l << "\n";
  cout << "R: " << e.r << "\n";
  cout << "TYPE: " << e.type << "\n\n";
}
int n, m;
vector<Event> S;
multiset<int> toBlock, ready;
int t[4 * MAX_N];
void update(int v, int l, int r, int pos, int val) {
  if (l == pos && r == pos) {
    t[v] += val;
    return;
  }
  if (r < pos || l > pos) return;
  int mid = (l + r) / 2;
  update(2 * v, l, mid, pos, val);
  update(2 * v + 1, mid + 1, r, pos, val);
  t[v] = t[2 * v] + t[2 * v + 1];
}
int query(int v, int l, int r, int qL, int qR) {
  if (qL <= l && r <= qR) return t[v];
  if (l > qR || r < qL) return 0;
  int mid = (l + r) / 2;
  return query(2 * v, l, mid, qL, qR) + query(2 * v + 1, mid + 1, r, qL, qR);
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> n >> m;
  for (int i = 0; i < n; i++) {
    int y, l, r;
    cin >> y >> l >> r;
    Event e = {l, y, y, START_HORI};
    S.push_back(e);
    e = {r, y, y, END_HORI};
    S.push_back(e);
  }
  for (int i = 0; i < m; i++) {
    int x, l, r;
    cin >> x >> l >> r;
    Event e = {x, l, r, VERTI};
    S.push_back(e);
  }
  S.push_back({0, 0, 0, START_HORI});
  S.push_back({0, M, M, START_HORI});
  S.push_back({M, 0, 0, END_HORI});
  S.push_back({M, M, M, END_HORI});
  S.push_back({0, 0, M, VERTI});
  S.push_back({M, 0, M, VERTI});
  sort(S.begin(), S.end());
  long long ans = 0LL;
  for (Event e : S) {
    if (e.type == START_HORI) {
      toBlock.insert(e.l + 1);
    }
    if (e.type == VERTI) {
      int tmp = query(1, 1, MAX_N - 1, e.l + 1, e.r + 1);
      ans += max(tmp - 1, 0);
      auto it2 = toBlock.lower_bound(e.l + 1);
      while (it2 != toBlock.end() && (*it2) <= e.r + 1) {
        ready.insert(*it2);
        update(1, 1, MAX_N - 1, *it2, 1);
        it2 = toBlock.erase(it2);
      }
    }
    if (e.type == END_HORI) {
      if (ready.count(e.l + 1)) {
        ready.erase(ready.find(e.l + 1));
        update(1, 1, MAX_N - 1, e.l + 1, -1);
      }
      if (toBlock.count(e.l + 1)) toBlock.erase(toBlock.find(e.l + 1));
    }
  }
  cout << ans << "\n";
  return 0;
}
