#include <bits/stdc++.h>
using namespace std;
const double PI = 2 * acos(0.0);
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
mt19937_64 rng_64(chrono::steady_clock::now().time_since_epoch().count());
const string DIGITS = "0123456789";
const string ALPH = "abcdefghijklmnopqrstuvwxyz";
template <class T0, class T1>
inline ostream &operator<<(ostream &out, pair<T0, T1> &a) {
  return out << "{" << a.first << ", " << a.second << "}";
}
template <class T0, class T1>
inline istream &operator>>(istream &in, pair<T0, T1> &a) {
  return in >> a.first >> a.second;
}
template <class T0, class T1, class T2>
inline ostream &operator<<(ostream &out, tuple<T0, T1, T2> &a) {
  return out << "{" << get<0>(a) << ", " << get<1>(a) << ", " << get<2>(a)
             << "}";
}
template <class T0, class T1, class T2, class T3>
inline ostream &operator<<(ostream &out, tuple<T0, T1, T2, T3> &a) {
  return out << "{" << get<0>(a) << ", " << get<1>(a) << ", " << get<2>(a)
             << ", " << get<3>(a) << "}";
}
template <class T>
inline ostream &operator<<(ostream &out, vector<T> &a) {
  out << "[";
  for (int i = 0; i < int(a.size()); ++i)
    out << a[i] << vector<string>{", ", "]  "}[i + 1 == a.size()];
  return out;
}
void smain();
signed main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cout << setprecision(12) << fixed;
  smain();
  return 0;
}
const int S = 1e6;
int t[(S + 1) << 2];
struct Tree {
  void upd(int v, int tl, int tr, int pos, int val) {
    if (tl == tr) {
      t[v] = val;
      return;
    }
    int tm = tl + tr >> 1;
    if (pos <= tm)
      upd(v << 1, tl, tm, pos, val);
    else
      upd(v << 1 | 1, tm + 1, tr, pos, val);
    t[v] = t[v << 1] + t[v << 1 | 1];
  }
  int get(int v, int tl, int tr, int l, int r) {
    if (l > r) return 0;
    if (tl == l && tr == r) return t[v];
    int tm = tl + tr >> 1;
    return get(v << 1, tl, tm, l, min(tm, r)) +
           get(v << 1 | 1, tm + 1, tr, max(tm + 1, l), r);
  }
};
const pair<int, int> bad = {-1, -1};
const pair<int, int> full = {0, S};
void smain() {
  vector<pair<int, pair<int, int>>> ver;
  int n, m;
  cin >> n >> m;
  Tree tree;
  vector<pair<int, int>> endhor, starthor;
  for (int _ = 0; _ < int(n); ++_) {
    int y, l, r;
    cin >> y >> l >> r;
    if (l == 0) {
      endhor.push_back({r, y});
      tree.upd(1, 0, S, y, 1);
    } else {
      starthor.push_back({l, y});
    }
  }
  for (int _ = 0; _ < int(m); ++_) {
    int x, l, r;
    cin >> x >> l >> r;
    ver.push_back({x, {l, r}});
  }
  ver.push_back({S, {0, S}});
  sort(ver.begin(), ver.end());
  int vri = 0;
  set<int> started;
  long long ans = 0;
  int si = 0, ei = 0;
  sort(starthor.begin(), starthor.end());
  sort(endhor.begin(), endhor.end());
  for (int x = 0; x < int(S + 1); ++x) {
    while (si < starthor.size() && starthor[si].first == x) {
      int y = starthor[si++].second;
      started.insert(y);
    }
    if (vri < ver.size() && ver[vri].first == x) {
      auto cur = ver[vri++].second;
      ans += tree.get(1, 0, S, cur.first, cur.second) + (cur == full);
      while (!started.empty()) {
        auto it = started.begin();
        if (cur.first <= *it && *it <= cur.second) {
          tree.upd(1, 0, S, *it, 1);
          started.erase(it);
        } else {
          break;
        }
      }
      while (!started.empty()) {
        auto it = prev(started.end());
        if (cur.first <= *it && *it <= cur.second) {
          tree.upd(1, 0, S, *it, 1);
          started.erase(it);
        } else {
          break;
        }
      }
    }
    while (ei < endhor.size() && endhor[ei].first == x) {
      int y = endhor[ei++].second;
      tree.upd(1, 0, S, y, 0);
    }
  }
  cout << ans;
}
