#include <bits/stdc++.h>
using namespace std;
class Graph {
  int V;
  vector<list<pair<long long, long long>>> adj;
  const int INF = (int)1e6;

 public:
  Graph(long long V) : adj(V) { this->V = V; }
  void addEdge(int u, int v, int w) { adj[u].push_back(make_pair(v, w)); }
  long long edgeNum() {
    long long sum = 0;
    for (int i = 0; i < V; i++) sum += adj[i].size();
    return sum;
  }
  bool route(long long from, long long to) {
    vector<long long> vec(V, -1);
    dfs(1, from, vec);
    return vec[to] >= 0;
  }
  void dfs(long long ed, long long num, vector<long long>& vec) {
    for (auto e : adj[num]) {
      if (vec[e.first] != -1) continue;
      vec[e.first] = num;
      dfs(ed + 1, e.first, vec);
    }
  }
  vector<int> bfs(int n) {
    queue<int> q;
    vector<int> vec(V, -1);
    q.push(n);
    vec[n] = 0;
    while (!q.empty()) {
      int pair<long long, long long> = q.front();
      q.pop();
      for (auto e : adj[pair<long long, long long>]) {
        if (vec[e.first] == -1) {
          q.push(e.first);
          vec[e.first] = e.second + vec[pair<long long, long long>];
        }
      }
    }
    return vec;
  }
  vector<int> shortestPath(int src) {
    priority_queue<pair<long long, long long>,
                   vector<pair<long long, long long>>,
                   greater<pair<long long, long long>>>
        pq;
    vector<int> dist(V, INF);
    pq.push(make_pair(0, src));
    dist[src] = 0;
    while (!pq.empty()) {
      int u = pq.top().second;
      pq.pop();
      list<pair<long long, long long>>::iterator i;
      for (auto i = adj[u].begin(); i != adj[u].end(); ++i) {
        int v = i->first;
        int weight = i->second;
        if (dist[v] > dist[u] + weight) {
          dist[v] = dist[u] + weight;
          pq.push(make_pair(dist[v], v));
        }
      }
    }
    for (int i = 0; i < V; i++)
      if (dist[i] == INF) dist[i] = -1;
    return dist;
  }
};
struct UF {
  vector<int> par, size;
  UF(int N) : par(N), size(N, 1) {
    for (int i = 0; i < N; i++) par[i] = i;
  }
  int root(int x) {
    if (par[x] == x) return x;
    return par[x] = root(par[x]);
  }
  void unite(int x, int y) {
    int rx = root(x);
    int ry = root(y);
    if (rx == ry) return;
    par[rx] = ry;
    size[rx] += size[ry];
  }
  bool same(int x, int y) {
    int rx = root(x);
    int ry = root(y);
    return rx == ry;
  }
  int getSize(int x) { return size[x]; }
};
struct BIT {
  vector<long long> tab;
  BIT(int n) : tab(n + 1) {
    for (int i = 0; i < n + 1; i++) tab[i] = 0;
  }
  void add(int pair<long long, long long>, long long num) {
    for (++pair<long long, long long>; pair<long long, long long> < tab.size();
         pair<long long, long long> +=
         pair<long long, long long> & -pair<long long, long long>)
      tab[pair<long long, long long>] += num;
  }
  long long sum(int pair<long long, long long>) {
    long long ans = 0;
    for (++pair<long long, long long>; pair < long long, long long >> 0;
         pair<long long, long long> -=
         pair<long long, long long> & -pair<long long, long long>)
      ans += tab[pair<long long, long long>];
    return ans;
  }
  void debug() {
    for (int i = 0; i < tab.size(); i++) cout << tab[i] << ' ';
    cout << endl;
  }
};
long long sum(pair<long long, long long> c) { return (c.first + c.second); }
pair<long long, long long> operator-(const pair<long long, long long>& l,
                                     const pair<long long, long long>& r) {
  return {l.first - r.first, l.second - r.second};
}
bool cmpf(const pair<long long, long long> left,
          const pair<long long, long long> right) {
  return left.first < right.first;
}
bool cmps(const pair<long long, long long> left,
          const pair<long long, long long> right) {
  return left.second < right.second;
}
long long gcd(long long a, long long b) {
  if (a < b) return gcd(b, a);
  long long temp;
  while ((temp = a % b)) {
    a = b;
    b = temp;
  }
  return b;
}
struct nCr {
  vector<long long> f, rf;
  long long count = 0;
  nCr(long long num) : f(num), rf(num) {
    count = num;
    f[0] = 1;
    for (int i = 1; i <= num; i++) f[i] = (f[i - 1] * i) % 1000000007;
    for (int i = 0; i < num + 1; i++) rf[i] = inv(f[i]);
  }
  long long inv(long long x) {
    long long res = 1;
    long long k = 1000000007 - 2;
    long long y = x;
    while (k) {
      if (k & 1) res = (res * y) % 1000000007;
      y = (y * y) % 1000000007;
      k /= 2;
    }
    return res;
  }
  long long C(long long n, long long k) {
    if (k > n || k < 0) return 0;
    long long a = f[n];
    long long b = rf[n - k];
    long long c = rf[k];
    long long bc = (b * c) % 1000000007;
    return (a * bc) % 1000000007;
  }
};
int main() {
  long long n, m;
  cin >> n >> m;
  vector<vector<long long>> vn(n, vector<long long>(3)),
      vm(m, vector<long long>(3));
  set<long long> mpv, mph;
  for (int i = 0; i < n; i++) {
    cin >> vn[i][0];
    mpv.insert(vn[i][0]);
    cin >> vn[i][1];
    mpv.insert(vn[i][1]);
    cin >> vn[i][2];
    mph.insert(vn[i][2]);
  }
  for (int i = 0; i < m; i++) {
    cin >> vm[i][2];
    mpv.insert(vm[i][2]);
    cin >> vm[i][0];
    mph.insert(vm[i][0]);
    cin >> vm[i][1];
    mph.insert(vm[i][1]);
  }
  mpv.insert(0);
  mph.insert(0);
  vector<long long> vecv(mpv.size()), vech(mph.size());
  auto itrv = mpv.begin();
  for (int i = 0; i < mpv.size(); i++) {
    vecv[i] = *itrv;
    itrv++;
  }
  auto itrh = mph.begin();
  for (int i = 0; i < mph.size(); i++) {
    vech[i] = *itrh;
    itrh++;
  }
  long long vsize = mpv.size() * 2 + 1, hsize = mph.size() * 2 + 1;
  vector<vector<long long>> table(vsize + 1, vector<long long>(hsize, 0)),
      check(vsize, vector<long long>(hsize, 0));
  vsize--;
  hsize--;
  for (int i = 0; i < n; i++) {
    for (auto itr = mpv.find(vn[i][0]); itr != mpv.find(vn[i][1]); itr++) {
    }
  }
  for (int i = 0; i < m; i++) {
    for (auto itr = mph.find(vm[i][0]); itr != mph.find(vm[i][1]); itr++) {
    }
  }
  queue<pair<long long, long long>> q;
  int st[][2] = {{1, 1}, {1, -1}, {-1, -1}, {-1, 1}};
  for (auto e : st)
    q.push({distance(mpv.begin(), mpv.find(0)) * 2 + 1 + e[0],
            distance(mph.begin(), mph.find(0)) * 2 + 1 + e[1]});
  long long ans = 0;
  int mov[][2] = {{0, 2}, {0, -2}, {2, 0}, {-2, 0}};
  while (!q.empty()) {
    pair<long long, long long> tp = q.front();
    q.pop();
    if (tp.first <= 0 || tp.first >= vsize || tp.second <= 0 ||
        tp.second >= hsize) {
      cout << "INF\n";
      return 0;
    } else {
      if (check[tp.first][tp.second] == 1) continue;
      ans += (vecv[tp.first / 2] - vecv[tp.first / 2 - 1]) *
             (vech[tp.second / 2] - vech[tp.second / 2 - 1]);
      check[tp.first][tp.second] = 1;
      for (auto e : mov) {
        if (table[e[0] / 2 + tp.first][e[1] / 2 + tp.second] == 0) {
          if (check[e[0] + tp.first][e[1] + tp.second] != 1) {
            q.push({e[0] + tp.first, e[1] + tp.second});
          }
        }
      }
    }
  }
  cout << ans << endl;
}
