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

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl





using ll = long long;

const ll inf = 1e10;
const int maxn = 1010;


int n, m;

ll A[maxn], B[maxn], C[maxn], D[maxn], E[maxn], F[maxn];

vector<ll> ordX, ordY;

int compress(ll x, const vector<ll> & ord) {
    return std::lower_bound(ord.begin(),ord.end(),x)-ord.begin();
}

int DX[4]={1,-1,0,0};
int DY[4]={0,0,1,-1};

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

    cin>>n>>m;
    for (int i=0; i<n; i++) {
	cin>>A[i]>>B[i]>>C[i];
	ordX.push_back(A[i]);
	ordX.push_back(B[i]);
	ordY.push_back(C[i]);
    }

    for (int i=0; i<m; i++) {
	cin>>D[i]>>E[i]>>F[i];
	ordX.push_back(D[i]);
	ordY.push_back(E[i]);
	ordY.push_back(F[i]);
    }

    ordX.push_back(-inf);
    ordX.push_back(+inf);
    ordX.push_back(0);

    ordY.push_back(-inf);
    ordY.push_back(+inf);
    ordY.push_back(0);

    sort(ordX.begin(),ordX.end());
    ordX.erase(unique(ordX.begin(),ordX.end()),ordX.end());

    sort(ordY.begin(),ordY.end());
    ordY.erase(unique(ordY.begin(),ordY.end()),ordY.end());



    int N = ordX.size();
    int M = ordY.size();
    
    vector<vector<vector<int>>> g(N, vector<vector<int>>(M, vector<int>(4, 1)));
    vector<vector<int>> viz(N, vector<int>(M, 0));



    auto flood = [&](int x, int y, int cc) {
	queue<pair<int,int>> qq;
	qq.emplace(x,y);
	vector<pair<int,int>> pts;
	while (qq.size()) {
	    auto cur = qq.front();
	    qq.pop();
	    int x = cur.first;
	    int y = cur.second;
	    if (x<0||y<0||x>=N||y>=M) continue;
	    if (viz[x][y]) continue;
	    pts.emplace_back(x,y);
	    viz[x][y]=cc;
	    for (int k=0; k<4; k++) {
		if (g[x][y][k]) {
		    int nx=DX[k]+x;
		    int ny=DY[k]+y;
		    qq.emplace(nx,ny);
		}
	    }
	}
	return (int)pts.size();
    };


    //0: down, 1: up, 2: right, 3: left


    //vertical
    for (int z=0; z<n; z++) {
	int xl=compress(A[z], ordX);
	int xr=compress(B[z], ordX);
	int y=compress(C[z], ordY);

	for (int i=xl+1; i<=xr; i++) {
	    g[i][y][2] = 0;
	    g[i][y+1][3] = 0;
	    //removeEdge(i,y,i,y+1);
	}

    }


    //horizonal
    for (int z=0; z<m; z++) {
	int x=compress(D[z], ordX);
	int yl=compress(E[z], ordY);
	int yr=compress(F[z], ordY);

	for (int j=yl+1; j<=yr; j++) {
	    g[x][j][0] = 0;
	    g[x+1][j][1] = 0;
	    //removeEdge(x,j,x+1,j);
	}
    }
    
    int cc=0;
    for (int i=0; i<N; i++) {
	for (int j=0; j<M; j++) {
	    if (!viz[i][j]) {
		flood(i,j,++cc);
	    }
	}
    }



    auto print = [&]() {
	for (int i=0; i<N; i++) {
	    for (int j=0; j<M; j++) {
		cout<<viz[i][j];
	    }
	    cout<<endl;
	}

    };

    vector<ll> sizes(cc+10, 0);

    for (int i=0; i<N; i++) {
	for (int j=0; j<M; j++) {
	    sizes[viz[i][j]]++;
	}
    }

    int at = viz[compress(0, ordX)][compress(0, ordY)];
    ll res = 0;

    //print();

    for (int i=0; i<N; i++) {
	for (int j=0; j<M; j++) {
	    if (viz[i][j] == at) {
		if (i==0 || j==0) {
		    out("INF");
		}
		ll dx = ordX[i]-ordX[i-1];
		ll dy = ordY[j]-ordY[j-1];
		// watch(dx);
		// watch(dy);
		ll square = dx*dy;
		res += square;
	    }
	}
    }

    cout<<res<<endl;
    
    
    return 0;
}


Measured memory_bytes: 663212