There is a grass field that stretches infinitely.

In this field, there is a negligibly small cow. Let (x, y) denote the point that is x\ \mathrm{cm} south and y\ \mathrm{cm} east of the point where the cow stands now. The cow itself is standing at (0, 0).

There are also N north-south lines and M east-west lines drawn on the field. The i-th north-south line is the segment connecting the points (A_i, C_i) and (B_i, C_i), and the j-th east-west line is the segment connecting the points (D_j, E_j) and (D_j, F_j).

What is the area of the region the cow can reach when it can move around as long as it does not cross the segments (including the endpoints)? If this area is infinite, print `INF` instead.

Constraints

* All values in input are integers between -10^9 and 10^9 (inclusive).
* 1 \leq N, M \leq 1000
* A_i < B_i\ (1 \leq i \leq N)
* E_j < F_j\ (1 \leq j \leq M)
* The point (0, 0) does not lie on any of the given segments.

Input

Input is given from Standard Input in the following format:


N M
A_1 B_1 C_1
:
A_N B_N C_N
D_1 E_1 F_1
:
D_M E_M F_M


Output

If the area of the region the cow can reach is infinite, print `INF`; otherwise, print an integer representing the area in \mathrm{cm^2}.

(Under the constraints, it can be proved that the area of the region is always an integer if it is not infinite.)

Examples

Input

5 6
1 2 0
0 1 1
0 2 2
-3 4 -1
-2 6 3
1 0 1
0 1 2
2 0 2
-1 -4 5
3 -2 4
1 2 4


Output

13


Input

6 1
-3 -1 -2
-3 -1 1
-2 -1 2
1 4 -2
1 4 -1
1 4 1
3 1 4


Output

INF
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#define INF (int)(1e9 + 7)
#define maxn 3010
#define maxm 1010
using namespace std;
int n, m;//n代表竖线
int mup[maxn][maxn];
int mdown[maxn][maxn];
int mleft[maxn][maxn];
int mright[maxn][maxn];
int vis[maxn][maxn];
long long ans=0;
pair<int, int> temp;
int tempx, tempy;
int newx, newy;
pair<int, int> dir[4] = { {0,-1},{0,1},{-1,0},{1,0} };
bool flag = 0;

int a[maxm], b[maxm], c[maxm];
int d[maxm], e[maxm], f[maxm];

vector<int> xs;//存横分割
int xsize,ysize;
vector<int> ys;
queue<pair<int, int> > qu;
int main() {
	scanf("%d%d", &n, &m);
	xs.push_back(-INF);
	xs.push_back(INF);
	ys.push_back(-INF);
	ys.push_back(INF);
	xs.push_back(0);
	ys.push_back(0);
	for (int i = 0; i < n; i++) {
		scanf("%d%d%d", &a[i], &b[i], &c[i]);
		xs.push_back(a[i]);
		xs.push_back(b[i]);
		ys.push_back(c[i]);
	}
	for (int i = 0; i < m; i++) {
		scanf("%d%d%d", &d[i], &e[i], &f[i]);
		xs.push_back(d[i]);
		ys.push_back(e[i]);
		ys.push_back(f[i]);
	}
	
	//离散化的传统艺能
	//1.排序
	sort(xs.begin(), xs.end());
	sort(ys.begin(), ys.end());
	//2.去重
	xs.resize(unique(xs.begin(), xs.end()) - xs.begin());
	ys.resize(unique(ys.begin(), ys.end()) - ys.begin());
	//块分完了
	//xs[0] xs[1] ... 所有横分割（升序）
	//ys[0] ys[1] ... 所有竖分割（升序）
	//存储我们的四个方位数组
	//lower_bound(begin(),end(),k) —— 返回一个区域内，大于等于k的下标
	//等于的功能
	//所有竖线
	for (int i = 0; i < n; i++) {
		int xx = lower_bound(ys.begin(), ys.end(), c[i]) - ys.begin(); //返回横坐标
		int yy1 = lower_bound(xs.begin(), xs.end(), a[i]) - xs.begin(); //返回纵坐标起点
		int yy2 = lower_bound(xs.begin(), xs.end(), b[i]) - xs.begin(); //返回纵坐标终点
		for (int j = yy1; j < yy2; j++) {
			//代表的是，线段所覆盖的所有块
			mup[j][xx] = 1;
			mdown[j][xx-1] = 1;
		}
	}
	for (int i = 0; i < m; i++) {
		int yy = lower_bound(xs.begin(), xs.end(), d[i]) - xs.begin(); 
		int xx1 = lower_bound(ys.begin(), ys.end(), e[i]) - ys.begin(); 
		int xx2 = lower_bound(ys.begin(), ys.end(), f[i]) - ys.begin(); 
		for (int j = xx1; j < xx2; j++) {
			//代表的是，线段所覆盖的所有块
			mleft[yy][j] = 1;
			mright[yy-1][j] = 1;
		}
	}
	int x = lower_bound(xs.begin(), xs.end(), 0) - xs.begin();
	int y = lower_bound(ys.begin(), ys.end(), 0) - ys.begin();
	qu.push(pair<int, int>{x, y});
	xsize = xs.size();
	ysize = ys.size();
	while (!qu.empty()) {
		temp = qu.front();
		qu.pop();
		tempx = temp.first;
		tempy = temp.second;

		if (vis[tempx][tempy])continue;
		ans += (long long)(xs[tempx + 1] - xs[tempx]) * (long long)(ys[tempy + 1] - ys[tempy]);
		vis[tempx][tempy] = 1;
		if (tempx <= 0 || tempy <= 0) 
		{
			flag = 1; break;
	}
		if (tempx >= xsize - 1 || tempy >= ysize - 1) {
			flag = 1; break;
		}
		for (int i = 0; i < 4; i++) {
			if (i == 0 && mup[tempx][tempy]) continue;
			if (i == 1 && mdown[tempx][tempy]) continue;
			if (i == 2 && mleft[tempx][tempy]) continue;
			if (i == 3 && mright[tempx][tempy]) continue;
			newx = tempx + dir[i].first;
			newy = tempy + dir[i].second;
			qu.push(pair<int, int>(newx,newy));
		}
	}
	if (flag)printf("INF");
	else printf("%lld",ans);

}