Read problem statements in [Hindi], [Bengali], [Mandarin Chinese], [Russian], and [Vietnamese] as well.

Chef has been researching ant colonies for many years and finally discovered all their secrets.

An ant colony consists of $N$ distinct lines (numbered $1$ through $N$) that pass through a point $\mathsf{O}$, which is the queen's home. For each valid $i$, there are $M_{i}$ ants on the $i$-th line.

For each valid $i$ and $j$, the $j$-th ant on the $i$-th line initially has a non-zero coordinate $X_{i,j}$ with the following meaning:
The distance of this ant from $\mathsf{O}$ is $|X_{i,j}|$.
Let's choose a direction along the $i$-th line from $\mathsf{O}$. The exact way in which this direction is chosen does not matter here, it only needs to be the same for all ants on the same line.
If $X_{i,j}$ is positive, this ant is at the distance $|X_{i,j}|$ from $\mathsf{O}$ in the chosen direction. Otherwise, it is at this distance from $\mathsf{O}$ in the opposite direction.

In other words, two ants $j$ and $k$ on a line $i$ are at the same side of $\mathsf{O}$ if the signs of $X_{i,j}$ and $X_{i,k}$ are the same or on opposite sides if the signs are different.

All ants move with the same constant speed. Initially, all of them are moving towards $\mathsf{O}$. Whenever two or more ants meet (possibly at $\mathsf{O}$), all of these ants turn around and start moving in the opposite directions with the same speed. We call this a *collision*. Even if an ant reaches $\mathsf{O}$ without meeting an ant there, it keeps moving in the same direction. An ant may change direction multiple times.

Help Chef find the total number of collisions between ants. Note that even if more than two ants meet, it counts as only one collision.

------  Input ------
The first line of the input contains a single integer $T$ denoting the number of test cases. The description of $T$ test cases follows.
The first line of each test case contains a single integer $N$.
$N$ lines follow. For each valid $i$, the $i$-th of these lines contains an integer $M_{i}$, followed by a space and $M_{i}$ space-separated integers $X_{i,1}, X_{i,2}, \ldots, X_{i,M_{i}}$.

------  Output ------
For each test case, print a single line containing one integer ― the number of collisions between ants.

------  Constraints ------
$1 ≤ T ≤ 1,000$
$1 ≤ N ≤ 2 \cdot 10^{5}$
$1 ≤ M_{i} ≤ 5 \cdot 10^{5}$ for each valid $i$
$1 ≤ |X_{i,j}| ≤ 10^{9}$ for each valid $i,j$
$X_{i,j} < X_{i,j+1}$ for each valid $i,j$
the sum of $N$ over all test cases does not exceed $2 \cdot 10^{5}$
the sum of $M_{1} + M_{2} + \ldots + M_{N}$ over all test cases does not exceed $10^{6}$

------  Subtasks ------
Subtask #1 (30 points): $N = 1$

Subtask #2 (70 points): original constraints

----- Sample Input 1 ------ 
1

2

2 -2 1

1 2
----- Sample Output 1 ------ 
2
----- explanation 1 ------ 
Example case 1: First, the ants on the first line collide at the coordinate $-1/2$ and change directions. Finally, ant $2$ on the first line collides with the only ant on the second line; this happens at $\mathsf{O}$. No collisions happen afterwards.

Difficulty: HARD
Tags: Implementation

Greedy algorithms
Skill types: Greedy algorithms

Starter code:

Solutions:
import sys

def getInput():
	return sys.stdin.readline().strip()

def getInt():
	return int(getInput())

def getInts():
	return map(int, getInput().split())

def getArray():
	return list(getInts())
tc = getInt()
for _ in range(tc):
	n = getInt()
	lines = []
	for __ in range(n):
		lines.append(getArray()[1:])
	mp = dict()
	for line in lines:
		for ant in line:
			if abs(ant) in mp:
				mp[abs(ant)] += 1
			else:
				mp[abs(ant)] = 1
	ans = 0
	for i in mp.values():
		if i >= 2:
			ans += 1
	for line in lines:
		neg = []
		pos = []
		for ant in line:
			if ant < 0:
				neg.append(ant)
			else:
				pos.append(ant)
		pos.reverse()
		while True:
			try:
				if abs(neg[-1]) < pos[-1]:
					closest = neg[-1]
				else:
					closest = pos[-1]
			except:
				if not neg and (not pos):
					break
				if not neg:
					closest = pos[-1]
				if not pos:
					closest = neg[-1]
			if mp[abs(closest)] >= 2:
				if closest < 0:
					ans += len(neg) - 1
				else:
					ans += len(pos) - 1
			elif closest < 0:
				ans += len(pos)
			else:
				ans += len(neg)
			if closest < 0:
				neg.pop()
			else:
				pos.pop()
	print(ans)


from functools import lru_cache
import sys
import math
from collections import Counter, deque
mod = 10 ** 9 + 7
inf = float('inf')

def arrInt():
	return list(map(int, input().split()))

def solve(n, ants):
	collisions = 0
	arr = []
	counter = Counter()
	pos = [0] * n
	neg = [0] * n
	for (i, row) in enumerate(ants):
		for el in row:
			counter[abs(el)] += 1
			if el < 0:
				neg[i] += 1
			else:
				pos[i] += 1
			arr.append((el, i))
	arr.sort(key=lambda x: abs(x[0]))
	for (d, v) in counter.items():
		collisions += int(v > 1)
	for (el, i) in arr:
		if counter[abs(el)] == 1:
			if el < 0:
				collisions += pos[i]
				neg[i] -= 1
			else:
				collisions += neg[i]
				pos[i] -= 1
		elif el < 0:
			neg[i] -= 1
			collisions += neg[i]
		else:
			pos[i] -= 1
			collisions += pos[i]
	print(collisions)
TESTING = False
if TESTING:
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')
else:
	input = sys.stdin.readline
T = int(input())
for _ in range(T):
	n = int(input())
	ants = []
	for _ in range(n):
		ants.append(arrInt()[1:])
	solve(n, ants)


t = int(input())
for i in range(t):
	n = int(input())
	d = {}
	l = []
	for j in range(n):
		neg = 0
		a = list(map(int, input().split()))
		for k in range(a[0]):
			if a[1 + k] < 0:
				neg += 1
				if abs(a[1 + k]) in d:
					d[abs(a[1 + k])].append([j + 1, 0])
				else:
					d[abs(a[1 + k])] = [[j + 1, 0]]
			elif a[1 + k] in d:
				if d[a[1 + k]][-1][0] == j + 1:
					d[a[1 + k]][-1][1] = 2
				else:
					d[a[1 + k]].append([j + 1, 1])
			else:
				d[a[1 + k]] = [[j + 1, 1]]
		l.append([neg, a[0] - neg])
	k = list(d.keys())
	k.sort()
	co = 0
	for j in k:
		if len(d[j]) == 1 and d[j][0][1] != 2:
			if d[j][0][1] == 0:
				l[d[j][0][0] - 1][0] -= 1
				co += l[d[j][0][0] - 1][1]
			else:
				l[d[j][0][0] - 1][1] -= 1
				co += l[d[j][0][0] - 1][0]
		else:
			co += 1
			for k in d[j]:
				if k[1] == 0 or k[1] == 2:
					l[k[0] - 1][0] -= 1
					co += l[k[0] - 1][0]
				if k[1] == 1 or k[1] == 2:
					l[k[0] - 1][1] -= 1
					co += l[k[0] - 1][1]
	print(co)


from bisect import bisect_left, bisect_right
for _ in range(int(input())):
	n = int(input())
	a = []
	c = {}
	ctr = 0
	for i in range(n):
		s = list(map(int, input().split()))
		m = int(s[0])
		a.append(s[1:])
		for j in a[-1]:
			if abs(j) in c:
				c[abs(j)] += 1
			else:
				c[abs(j)] = 1
	ans = 0
	for k in c.values():
		if k > 1:
			ans += 1
	for i in range(n):
		for j in range(len(a[i])):
			if c[abs(a[i][j])] <= 1:
				if a[i][j] < 0:
					ans += len(a[i]) - bisect_right(a[i], -a[i][j])
				else:
					ans += bisect_left(a[i], -a[i][j])
			elif a[i][j] < 0:
				ans += j
			else:
				ans += len(a[i]) - (j + 1)
	print(ans)


import math
try:
	t = int(input())
	for _ in range(t):
		n = int(input())
		lines = []
		for __ in range(n):
			lines.append(list(map(int, input().split()))[1:])
		mapp = dict()
		for line in lines:
			for ant in line:
				if abs(ant) in mapp:
					mapp[abs(ant)] += 1
				else:
					mapp[abs(ant)] = 1
		ans = 0
		for i in mapp.values():
			if i > 1:
				ans += 1
		for line in lines:
			pos = []
			neg = []
			for ant in line:
				if ant < 0:
					neg.append(ant)
				else:
					pos.append(ant)
			pos.reverse()
			while True:
				closest = 0
				if not neg and (not pos):
					break
				elif not neg:
					closest = pos[-1]
				elif not pos:
					closest = neg[-1]
				else:
					closest = neg[-1] if abs(neg[-1]) < pos[-1] else pos[-1]
				if mapp[abs(closest)] > 1:
					if closest < 0:
						ans += len(neg) - 1
					else:
						ans += len(pos) - 1
				elif closest < 0:
					ans += len(pos)
				else:
					ans += len(neg)
				if closest < 0:
					neg.pop()
				else:
					pos.pop()
		print(ans)
except EOFError as t:
	pass


from collections import Counter

def countGreater(arr, n, k):
	l = 0
	r = n - 1
	leftGreater = n
	while l <= r:
		m = int(l + (r - l) / 2)
		if arr[m] > k:
			leftGreater = m
			r = m - 1
		else:
			l = m + 1
	return n - leftGreater
for i in range(int(input())):
	n = int(input())
	c = []
	if n == 1:
		for i in range(n):
			c = [int(x) for x in input().split()]
		c.pop(0)
		x = 0
		y = 0
		for i in c:
			if i > 0:
				x = x + 1
			if i < 0:
				y = y + 1
		if y == len(c) or x == len(c):
			print(0)
		else:
			print(x * y)
	else:
		d = [[] for _ in range(n)]
		e = [[] for _ in range(n)]
		f = []
		ans = 0
		for i in range(n):
			c = [int(x) for x in input().split()]
			for j in c[1:]:
				f.append(abs(j))
				if j > 0:
					d[i].append(j)
				else:
					e[i].append(abs(j))
		for i in d:
			i.sort()
		for j in e:
			j.sort()
		t = Counter(f).items()
		t = dict(t)
		for i in t.values():
			if i > 1:
				ans = ans + 1
		for i in range(len(d)):
			for j in range(len(d[i])):
				if t[d[i][j]] > 1:
					ans = ans + len(d[i]) - j - 1
				elif len(e[i]) == 0:
					pass
				else:
					ans = ans + countGreater(e[i], len(e[i]), d[i][j])
		for i in range(len(e)):
			for j in range(len(e[i])):
				if t[e[i][j]] > 1:
					ans = ans + len(e[i]) - j - 1
				elif len(d[i]) == 0:
					pass
				else:
					ans = ans + countGreater(d[i], len(d[i]), e[i][j])
		print(ans)


from sys import stdin, stdout
for _ in range(int(stdin.readline())):
	n = int(stdin.readline())
	lines = []
	m = []
	ans = 0
	for i in range(n):
		l = list(map(int, stdin.readline().strip().split()))[1:]
		lines.append(l)
	f = {}
	for line in lines:
		for ant in line:
			if abs(ant) in f:
				f[abs(ant)] += 1
			else:
				f[abs(ant)] = 1
	for i in f.values():
		if i >= 2:
			ans += 1
	for line in lines:
		neg = []
		pos = []
		for i in line:
			if i < 0:
				neg.append(i)
			else:
				pos.append(i)
		pos.reverse()
		while True:
			try:
				if abs(neg[-1]) > abs(pos[-1]):
					close = pos[-1]
				else:
					close = neg[-1]
			except:
				if not neg and (not pos):
					break
				if not neg:
					close = pos[-1]
				if not pos:
					close = neg[-1]
			if f[abs(close)] >= 2:
				if close < 0:
					ans += len(neg) - 1
				else:
					ans += len(pos) - 1
			elif close < 0:
				ans += len(pos)
			else:
				ans += len(neg)
			if close < 0:
				neg.pop()
			else:
				pos.pop()
	print(ans)


for i in range(int(input())):
	n = int(input())
	lines = []
	ans = 0
	for i in range(n):
		l = list(map(int, input().split()[1:]))
		lines.append(l)
	mp = dict()
	for i in lines:
		for j in i:
			if abs(j) not in mp:
				mp[abs(j)] = 1
			elif abs(j) in mp:
				mp[abs(j)] += 1
	for value in mp.values():
		if value >= 2:
			ans += 1
	for line in lines:
		pos = []
		neg = []
		closest = 0
		for ant in line:
			if ant < 0:
				neg.append(ant)
			else:
				pos.append(ant)
		pos.sort(reverse=True)
		while True:
			if not neg and (not pos):
				break
			elif not neg:
				closest = pos[-1]
			elif not pos:
				closest = neg[-1]
			elif abs(neg[-1]) < pos[-1]:
				closest = neg[-1]
			else:
				closest = pos[-1]
			if mp[abs(closest)] >= 2:
				if closest < 0:
					ans += len(neg) - 1
				else:
					ans += len(pos) - 1
			elif closest < 0:
				ans += len(pos)
			else:
				ans += len(neg)
			if closest < 0:
				neg.pop()
			else:
				pos.pop()
	print(ans)


from heapq import heappush, heappop
from collections import defaultdict
for _ in range(int(input())):
	n = int(input())
	left = defaultdict(int)
	right = defaultdict(int)
	closest = []
	for i in range(n):
		ants = [int(s) for s in input().strip().split(' ')][1:]
		for a in ants:
			if a < 0:
				left[i] += 1
			else:
				right[i] += 1
			heappush(closest, (abs(a), i, a))
	ans = 0
	while len(closest) > 0:
		d = closest[0][0]
		colliding = []
		while len(closest) > 0 and closest[0][0] == d:
			(_, i, a) = heappop(closest)
			colliding.append((i, a))
		if len(colliding) == 1:
			(i, a) = colliding[0]
			if a > 0:
				right[i] -= 1
				ans += left[i]
			else:
				left[i] -= 1
				ans += right[i]
		else:
			ans += 1
			for (i, a) in colliding:
				if a > 0:
					right[i] -= 1
				else:
					left[i] -= 1
			for (i, a) in colliding:
				if a > 0:
					ans += right[i]
				else:
					ans += left[i]
	print(ans)


from sys import stdin, stdout

def solver(larr, rarr, s):
	(i, j) = (0, 0)
	temp = 0
	while len(larr) > 0 and len(rarr) > 0:
		if abs(larr[i]) < rarr[j]:
			if abs(larr[i]) in s:
				temp += len(larr) - 1
			else:
				temp += len(rarr)
			larr.remove(larr[0])
		else:
			if rarr[j] in s:
				temp += len(rarr) - 1
			else:
				temp += len(larr)
			rarr.remove(rarr[0])
	if len(larr) > 0:
		while len(larr) > 0:
			if abs(larr[0]) in s:
				temp += len(larr) - 1
			larr.remove(larr[0])
	if len(rarr) > 0:
		while len(rarr) > 0:
			if rarr[0] in s:
				temp += len(rarr) - 1
			rarr.remove(rarr[0])
	return temp
test = int(stdin.readline())
for testcase in range(test):
	n = int(stdin.readline())
	li = []
	d = {}
	for _ in range(n):
		arr = list(map(int, stdin.readline().split()))
		arr = arr[1:]
		(l, r) = ([], [])
		for ele in arr:
			if ele < 0:
				l.append(ele)
			else:
				r.append(ele)
			if abs(ele) in d:
				d[abs(ele)] += 1
			else:
				d[abs(ele)] = 1
		l = sorted(l, reverse=False)
		l = l[::-1]
		r.sort()
		p = [l, r]
		li.append(p)
	if n == 1:
		print(len(l) * len(r))
		continue
	s = set()
	ans = 0
	for ele in d:
		if d[ele] > 1:
			s.add(ele)
			ans += 1
	for ele in li:
		(left_arr, right_arr) = (ele[0], ele[1])
		tempo = solver(left_arr, right_arr, s)
		ans += tempo
	print(ans)


for _ in range(int(input())):
	n = int(input())
	l = []
	d = {}
	sum = 0
	(uniPos, uniNeg) = ({}, {})
	for i in range(n):
		(neg, pos) = (0, 0)
		(nList, pList) = ([], [])
		l = list(map(int, input().split()))
		for j in range(1, len(l)):
			if l[j] > 0:
				pos += 1
				pList.append(l[j])
			else:
				neg += 1
				nList.append(l[j])
			if abs(l[j]) not in d:
				d[abs(l[j])] = 0
			d[abs(l[j])] += 1
		pList.sort(reverse=True)
		uniPos[i] = pList
		uniNeg[i] = nList
	for i in d:
		if d[i] > 1:
			sum += 1
	for i in range(n):
		while True:
			closest = 0
			if len(uniNeg[i]) == 0 and len(uniPos[i]) == 0:
				break
			elif len(uniNeg[i]) == 0:
				closest = uniPos[i].pop()
			elif len(uniPos[i]) == 0:
				closest = uniNeg[i].pop()
			else:
				(a, b) = (uniNeg[i].pop(), uniPos[i].pop())
				if abs(a) > b:
					closest = b
					uniNeg[i].append(a)
				else:
					closest = a
					uniPos[i].append(b)
			if closest < 0:
				if d[abs(closest)] > 1:
					sum += len(uniNeg[i])
				else:
					sum += len(uniPos[i])
			elif d[abs(closest)] > 1:
				sum += len(uniPos[i])
			else:
				sum += len(uniNeg[i])
	print(sum)


t = int(input())
for _ in range(t):
	n = int(input())
	lines = []
	for i in range(n):
		lines.append(list(map(int, input().split()[1:])))
	mp = {}
	for line in lines:
		for ant in line:
			if abs(ant) in mp:
				mp[abs(ant)] += 1
			else:
				mp[abs(ant)] = 1
	ans = 0
	for i in mp.values():
		if i >= 2:
			ans += 1
	for line in lines:
		neg = []
		pos = []
		for ant in line:
			if ant < 0:
				neg.append(ant)
			else:
				pos.append(ant)
		pos.reverse()
		while True:
			try:
				if abs(neg[-1]) < pos[-1]:
					closest = neg[-1]
				else:
					closest = pos[-1]
			except:
				if not neg and (not pos):
					break
				if not neg:
					closest = pos[-1]
				if not pos:
					closest = neg[-1]
			if mp[abs(closest)] >= 2:
				if closest < 0:
					ans += len(neg) - 1
				else:
					ans += len(pos) - 1
			elif closest < 0:
				ans += len(pos)
			else:
				ans += len(neg)
			if closest < 0:
				neg.pop()
			else:
				pos.pop()
	print(ans)


from sys import stdin, stdout
from bisect import bisect_left, bisect_right
from math import ceil
from copy import deepcopy
from collections import deque
for test in range(int(stdin.readline())):
	n = int(stdin.readline())
	voca = []
	doco = {}
	for i in range(n):
		ar = list(map(int, stdin.readline().split()))
		voca.append(sorted(ar[1:]))
		for j in voca[-1]:
			if abs(j) in doco:
				doco[abs(j)] += 1
			else:
				doco[abs(j)] = 1
	asdfe = 0
	for i in doco.values():
		if i > 1:
			asdfe += 1
	for i in range(n):
		for j in range(len(voca[i])):
			if doco[abs(voca[i][j])] <= 1:
				if voca[i][j] > 0:
					asdfe += bisect_left(voca[i], -voca[i][j])
				else:
					asdfe += len(voca[i]) - bisect_right(voca[i], -voca[i][j])
			elif voca[i][j] > 0:
				asdfe += len(voca[i]) - (j + 1)
			else:
				asdfe += j
	print(asdfe)


def arr():
	return list(map(int, input().split()))
T = int(input())
for _ in range(T):
	n = int(input())
	ants = []
	rem = []
	for i in range(n):
		(m, *pos) = arr()
		rem.append([0, 0])
		for x in pos:
			if x > 0:
				ants.append((x, i, 0))
				rem[-1][0] += 1
			else:
				ants.append((-x, i, 1))
				rem[-1][1] += 1
	ants.sort()
	n_ants = len(ants)
	ans = 0
	i = 0
	while i < n_ants:
		a = [ants[i]]
		i += 1
		while i < n_ants and ants[i][0] == a[0][0]:
			a.append(ants[i])
			i += 1
		if len(a) > 1:
			ans += 1
			for ant in a:
				rem[ant[1]][ant[2]] -= 1
				ans += rem[ant[1]][ant[2]]
		else:
			ant = a[0]
			rem[ant[1]][ant[2]] -= 1
			ans += rem[ant[1]][1 - ant[2]]
	print(ans)


t = int(input())
for _ in range(t):
	n = int(input())
	lines = []
	ans = 0
	maps = dict()
	for i in range(n):
		m = list(map(int, input().split()))
		lis = m[1:]
		for val in lis:
			if abs(val) in maps:
				maps[abs(val)] += 1
			else:
				maps[abs(val)] = 1
		lines.append(lis)
	for (key, val) in maps.items():
		if val > 1:
			ans += 1
	for line in lines:
		neg = []
		pos = []
		for i in line:
			if i < 0:
				neg.append(i)
			else:
				pos.append(i)
		pos.sort(reverse=True)
		while True:
			closest = 0
			if len(neg) <= 0 and len(pos) <= 0:
				break
			elif len(neg) == 0:
				closest = pos[-1]
			elif len(pos) == 0:
				closest = neg[-1]
			else:
				closest = neg[-1] if abs(neg[-1]) < pos[-1] else pos[-1]
			if closest < 0:
				if maps[abs(closest)] > 1:
					ans += len(neg) - 1
				else:
					ans += len(pos)
			elif maps[abs(closest)] > 1:
				ans += len(pos) - 1
			else:
				ans += len(neg)
			if closest < 0:
				neg.pop(-1)
			else:
				pos.pop(-1)
	print(ans)


from collections import defaultdict
T = int(input())
for t in range(T):
	n = int(input())
	lines = []
	for line in range(n):
		xx = [int(i) for i in input().split()]
		m = xx[0]
		A = xx[1:]
		lines.append(A)
	ans = 0
	universal_ants_away_from_origin_by = defaultdict(int)
	unique_distances = []
	for line in lines:
		for ant in line:
			universal_ants_away_from_origin_by[abs(ant)] += 1
			if universal_ants_away_from_origin_by[abs(ant)] == 1:
				unique_distances.append(abs(ant))
	for line in lines:
		neg = 0
		pos = 0
		line_state = []
		for point in line:
			if point > 0:
				pos += 1
				line_state.append([point, 1])
			else:
				neg += 1
				line_state.append([abs(point), -1])
		line_state.sort()
		for (point, sign) in line_state:
			if sign == 1:
				pos -= 1
			else:
				neg -= 1
			if universal_ants_away_from_origin_by[point] > 1:
				if sign == 1:
					ans += pos
				else:
					ans += neg
			elif sign == 1:
				ans += neg
			else:
				ans += pos
	for pt in universal_ants_away_from_origin_by:
		if universal_ants_away_from_origin_by[pt] > 1:
			ans += 1
	print(ans)


t = int(input())
for _ in range(t):
	n = int(input())
	lines = []
	dist = {}
	for _ in range(n):
		temp = list(map(int, input().split()))
		lines.append(temp[1:])
		for i in temp[1:]:
			dist[abs(i)] = dist.get(abs(i), 0) + 1
	res = 0
	for i in range(n):
		pos = 0
		neg = 0
		line = []
		for j in lines[i]:
			if j < 0:
				neg += 1
				line.append([abs(j), -1])
			else:
				pos += 1
				line.append([abs(j), 1])
		line.sort()
		for j in line:
			if j[1] == 1:
				pos -= 1
			else:
				neg -= 1
			if dist[j[0]] > 1:
				if j[1] == 1:
					res += pos
				else:
					res += neg
			elif j[1] == -1:
				res += pos
			else:
				res += neg
	for i in dist:
		if dist[i] > 1:
			res += 1
	print(res)


from collections import defaultdict
for _ in range(int(input())):
	n = int(input())
	if n == 1:
		r = list(map(int, input().split()))
		(cp, cn) = (0, 0)
		for i in range(1, len(r)):
			if r[i] < 0:
				cn += 1
			else:
				cp += 1
		print(cp * cn)
	else:
		lines = []
		distances = []
		d = defaultdict(lambda : 0)
		for _ in range(n):
			l = list(map(int, input().split()))
			for i in l[1:]:
				d[abs(i)] += 1
				if d[abs(i)] == 1:
					distances.append(abs(i))
			lines.append(l[1:])
		total = 0
		for line in lines:
			s = []
			(cp, cn) = (0, 0)
			for e in line:
				if e > 0:
					cp += 1
					s.append((e, 1))
				else:
					cn += 1
					s.append((abs(e), -1))
			s = sorted(s, key=lambda x: x[0])
			for (x, y) in s:
				if y == -1:
					cn -= 1
				else:
					cp -= 1
				if d[x] > 1:
					if y == -1:
						total += cn
					else:
						total += cp
				elif y == 1:
					total += cn
				else:
					total += cp
		for point in distances:
			if d[point] > 1:
				total += 1
		print(total)


for _ in range(int(input())):
	n = int(input())
	ants = []
	dist = {}
	ans = 0
	for i in range(n):
		mi = list(map(int, input().split()))
		m = mi.pop(0)
		(pos, neg) = ([], [])
		for j in range(m):
			d = mi[j]
			if abs(d) in dist:
				dist[abs(d)] += 1
			else:
				dist[abs(d)] = 1
			if d > 0:
				pos.append(d)
			else:
				neg.append(d)
		pos.sort(reverse=True)
		neg.sort()
		ants.append([pos, neg])
	for i in dist:
		if dist[i] > 1:
			ans += 1
	for i in range(n):
		(pos, neg) = ants[i]
		while len(pos) > 0 and len(neg) > 0:
			if pos[-1] < abs(neg[-1]):
				a = pos.pop()
				if dist[a] > 1:
					ans += len(pos)
				else:
					ans += len(neg)
			else:
				a = neg.pop()
				if dist[abs(a)] > 1:
					ans += len(neg)
				else:
					ans += len(pos)
		while len(pos) > 0:
			a = pos.pop()
			if dist[a] > 1:
				ans += len(pos)
		while len(neg) > 0:
			a = neg.pop()
			if dist[abs(a)] > 1:
				ans += len(neg)
	print(ans)


t = int(input())
t1 = 0
while t1 < t:
	n = int(input())
	d = {}
	l = []
	for i in range(n):
		a = list(map(int, input().split()))
		l.append(a)
		for j in range(1, a[0] + 1):
			if abs(a[j]) not in d:
				d[abs(a[j])] = []
				if a[j] > 0:
					d[abs(a[j])].append([1, i, j - 1])
				else:
					d[abs(a[j])].append([-1, i, j - 1])
			elif a[j] > 0:
				d[abs(a[j])].append([1, i, j - 1])
			else:
				d[abs(a[j])].append([-1, i, j - 1])
	ans = 0
	l2 = []
	for j1 in range(n):
		l2.append([0, 0])
	for k in sorted(d.keys()):
		if len(d[k]) > 1:
			ans += 1
			for k1 in d[k]:
				if k1[0] == -1:
					pos = k1[2]
					ans += pos
					l_no = k1[1]
					l2[l_no][1] += 1
				else:
					l_no = k1[1]
					pos = k1[2] - l2[l_no][0] - l2[l_no][1]
					total = l[l_no][0] - l2[l_no][0] - l2[l_no][1]
					ans += total - pos - 1
					l2[l_no][0] += 1
		elif d[k][0][0] == -1:
			l_no = d[k][0][1]
			s1 = l2[l_no][0] + l2[l_no][1]
			total = l[l_no][0] - s1
			ans += total - d[k][0][2] - 1
			l2[l_no][1] += 1
		else:
			l_no = d[k][0][1]
			s1 = l2[l_no][0] + l2[l_no][1]
			total = l[l_no][0] - s1
			pos = d[k][0][2] - s1
			ans += pos
			l2[l_no][0] += 1
	print(ans)
	t1 += 1


def solve(N, Xneg, Xpos):
	if N == 1:
		return len(Xneg[1]) * len(Xpos[1])
	distances = {}
	for i in range(1, N + 1):
		for x in Xneg[i]:
			if x not in distances:
				distances[x] = []
			distances[x].append(-i)
		for x in Xpos[i]:
			if x not in distances:
				distances[x] = []
			distances[x].append(i)
	positions = sorted([x for x in distances])
	collisions = 0
	for x in positions:
		if len(distances[x]) > 1:
			collisions += 1
			for line in distances[x]:
				if line > 0:
					collisions += len(Xpos[line]) - 1
					Xpos[line].pop(0)
				if line < 0:
					collisions += len(Xneg[-line]) - 1
					Xneg[-line].pop(0)
		else:
			line = distances[x][0]
			if line > 0:
				collisions += len(Xneg[line])
				Xpos[line].pop(0)
			if line < 0:
				collisions += len(Xpos[-line])
				Xneg[-line].pop(0)
	return collisions
T = int(input().strip())
for problem in range(1, T + 1):
	N = int(input().strip())
	(Xpos, Xneg) = ([None], [None])
	for line in range(N):
		inp = list(map(int, input().strip().split()))
		M = inp[0]
		Xpos.append(sorted([x for x in inp[1:] if x >= 0]))
		Xneg.append(sorted([-x for x in inp[1:] if x <= 0]))
	print(solve(N, Xneg, Xpos))


import sys
MOD = 1000000007

def get_ints():
	return map(int, sys.stdin.readline().strip().split())

def get_int():
	return int(sys.stdin.readline())

def get_line():
	return sys.stdin.readline().strip()

def write_line(out):
	return sys.stdout.write(str(out) + '\n')

def count_pos_and_neg(arr):
	pos = 0
	neg = 0
	for val in arr:
		if val > 0:
			pos += 1
		else:
			neg += 1
	return [pos, neg]

def make_tuples(arr):
	res = []
	for val in arr:
		if val < 0:
			res.append((abs(val), -1))
		else:
			res.append((abs(val), 1))
	res.sort(key=lambda pair: pair[0])
	return res

def solve():
	n = get_int()
	lines = []
	for i in range(n):
		temp = list(get_ints())
		temp.pop(0)
		lines.append(temp)
	equidistant_points = dict()
	for line in lines:
		for val in line:
			if abs(val) in equidistant_points:
				equidistant_points[abs(val)] += 1
			else:
				equidistant_points[abs(val)] = 1
	ans = 0
	for line in lines:
		sign_count = count_pos_and_neg(line)
		temp = make_tuples(line)
		for val in temp:
			if val[1] == 1:
				sign_count[0] -= 1
			else:
				sign_count[1] -= 1
			if equidistant_points[val[0]] > 1:
				if val[1] == 1:
					ans += sign_count[0]
				else:
					ans += sign_count[1]
			elif val[1] == 1:
				ans += sign_count[1]
			else:
				ans += sign_count[0]
	for val in equidistant_points.values():
		if val > 1:
			ans += 1
	return ans
t = get_int()
while t:
	write_line(solve())
	t -= 1


for i in range(int(input())):
	N = int(input())
	lines = []
	for i in range(N):
		curr = list(map(int, input().split()))
		lines.append(curr[1:])
	frequency = {}
	occur = {}
	pos = []
	for i in lines:
		for j in i:
			pos.append(abs(j))
	for i in pos:
		if i in occur:
			occur[i] += 1
		else:
			occur[i] = 1
	for i in occur:
		if occur[i] > 1:
			frequency[i] = occur[i]
	ans = 0
	for curr_line in lines:
		totalants = len(curr_line)
		d = {}
		for i in curr_line:
			d[i] = True
		imaginary = {}
		for i in d:
			if -i not in d:
				imaginary[-i] = True
		currNC = 0
		currC = 0
		colliding = {}
		noncolliding = {}
		indices = []
		for i in imaginary:
			indices.append(i)
		indices.extend(curr_line)
		indices.append(0)
		indices.sort()
		for ind in indices:
			if ind in imaginary or ind == 0:
				colliding[ind] = currC
				noncolliding[ind] = currNC
			elif abs(ind) in frequency:
				colliding[ind] = currC
				noncolliding[ind] = currNC
				currC += 1
			else:
				colliding[ind] = currC
				noncolliding[ind] = currNC
				currNC += 1
		for ind in curr_line:
			NC4C4 = totalants - noncolliding[abs(ind)] - colliding[abs(ind)]
			NC3 = noncolliding[abs(ind)] - noncolliding[0]
			C3 = colliding[abs(ind)] - colliding[0]
			if abs(ind) in d:
				if abs(ind) not in frequency:
					NC3 -= 1
				else:
					C3 -= 1
			NC2 = noncolliding[0] - noncolliding[-abs(ind)]
			C2 = colliding[0] - colliding[-abs(ind)]
			NC1 = noncolliding[-abs(ind)]
			C1 = colliding[-abs(ind)]
			if -abs(ind) in d:
				if abs(ind) not in frequency:
					NC1 -= 1
				else:
					C1 -= 1
			LNC = NC4C4 + NC3 + C2
			RNC = NC1 + C1 + NC2 + C3
			LC = NC1 + C1 + NC3 + C2
			RC = NC4C4 + NC2 + C3
			if ind < 0:
				if abs(ind) in frequency:
					ans += LC
				else:
					ans += LNC
			elif abs(ind) in frequency:
				ans += RC
			else:
				ans += RNC
	ans = ans // 2
	ans += len(frequency)
	print(ans)


from collections import Counter
from bisect import bisect_right as br
t = int(input())
for _ in range(t):
	n = int(input())
	if n == 1:
		loc = list(input().split())
		m = int(loc[0])
		loc.pop(0)
		coll = 0
		l = 0
		for i in range(m):
			loc[i] = int(loc[i])
			if loc[i] < 0:
				l += 1
			else:
				coll += l
		print(coll)
	else:
		(lines, m) = ([], [])
		pos = []
		(occr, occ) = ({}, {})
		lr = {}
		di = []
		for i in range(n):
			li = list(map(int, input().split()))
			m1 = li.pop(0)
			m.append(m1)
			k1 = br(li, 0)
			pos.append([k1, m1 - k1])
			d = []
			for j in range(m1):
				k = abs(li[j])
				if li[j] < 0:
					try:
						lr[k] += j
					except:
						lr[k] = j
				else:
					try:
						lr[k] += m1 - j - 1
					except:
						lr[k] = m1 - j - 1
				try:
					occr[k] += 1
				except:
					occr[k] = 1
					d.append(li[j])
			d = li.copy()
			d = sorted(d, key=lambda x: abs(x))
			di.append(d)
		ans = 0
		for i in range(n):
			for el in di[i]:
				if occr[abs(el)] == 1:
					if el < 0:
						ans += pos[i][1]
						pos[i][0] -= 1
					else:
						ans += pos[i][0]
						pos[i][1] -= 1
				elif el < 0:
					pos[i][0] -= 1
				else:
					pos[i][1] -= 1
		for i in occr:
			if occr[i] > 1:
				ans += lr[i] + 1
		print(ans)


test = int(input())
for i in range(0, test):
	lines = int(input())
	input_dict = {}
	answer = 0
	frequencies = {}
	for j in range(0, lines):
		a = list(map(int, input().split()))
		a.pop(0)
		neg_list = []
		pos_list = []
		for p in a:
			if p < 0:
				neg_list.append(p)
			else:
				pos_list.append(p)
			try:
				frequencies[abs(p)] += 1
			except:
				frequencies[abs(p)] = 1
		pos_list.reverse()
		input_dict[j] = {'negatives': neg_list, 'positives': pos_list}
	for j in range(0, lines):
		new_dict = input_dict[j]
		negatives = new_dict['negatives']
		positives = new_dict['positives']
		while True:
			if len(negatives) == 0 and len(positives) == 0:
				break
			elif len(negatives) == 0:
				closest = positives[-1]
			elif len(positives) == 0:
				closest = negatives[-1]
			else:
				closest = positives[-1] if abs(negatives[-1]) > positives[-1] else negatives[-1]
			if closest < 0:
				if frequencies[abs(closest)] > 1:
					answer = answer + len(negatives) - 1
				else:
					answer = answer + len(positives)
				negatives.pop()
			else:
				if frequencies[closest] > 1:
					answer = answer + len(positives) - 1
				else:
					answer = answer + len(negatives)
				positives.pop()
	for key in frequencies.keys():
		if frequencies[key] > 1:
			answer += 1
	print(answer)


import sys

def main():
	pass

def binary(n):
	return bin(n).replace('0b', '')

def decimal(s):
	return int(s, 2)

def pow2(n):
	p = 0
	while n > 1:
		n //= 2
		p += 1
	return p

def isPrime(n):
	if n == 1:
		return False
	else:
		root = int(n ** 0.5)
		root += 1
		for i in range(2, root):
			if n % i == 0:
				return False
		return True

def lts(l):
	s = ''.join(map(str, l))
	return s

def stl(s):
	l = list(s)
	return l

def sq(a, target, arr=[]):
	s = sum(arr)
	if s == target:
		return arr
	if s >= target:
		return
	for i in range(len(a)):
		n = a[i]
		remaining = a[i + 1:]
		ans = sq(remaining, target, arr + [n])
		if ans:
			return ans
mod = int(1000000000.0) + 7

def ssinp():
	return sys.stdin.readline().strip()

def iinp():
	return int(input())

def nninp():
	return map(int, sys.stdin.readline().strip().split())

def llinp():
	return list(map(int, sys.stdin.readline().strip().split()))

def p(xyz):
	print(xyz)

def p2(a, b):
	print(a, b)
import math
from collections import OrderedDict
for _ in range(iinp()):
	n = iinp()
	d = {}
	ans = 0
	l = []
	for __ in range(n):
		m = llinp()
		pos = neg = 0
		for i in range(len(m)):
			if i == 0:
				pass
			else:
				if m[i] > 0:
					pos += 1
				else:
					neg += 1
				if abs(m[i]) in d:
					d[abs(m[i])] += 1
				else:
					d[abs(m[i])] = 1
		m.append(pos)
		m.append(neg)
		l.append(m)
	for c in l:
		pos = c[-2]
		neg = c[-1]
		c[0] = 0
		c[-1] = 0
		c[-2] = 0
		s = set(c)
		l1 = sorted(c, key=abs)
		for i in l1:
			if i == 0:
				pass
			elif i > 0:
				if -1 * i in s:
					ans += neg
					pos -= 1
				elif d[abs(i)] > 1:
					pos -= 1
					ans += pos
				else:
					ans += neg
					pos -= 1
			elif -1 * i in s:
				ans += pos - 1
				neg -= 1
			elif d[abs(i)] > 1:
				neg -= 1
				ans += neg
			else:
				ans += pos
				neg -= 1
	for key in d:
		if d[key] > 1:
			ans += 1
	print(ans)


t = int(input())
for _ in range(t):
	n = int(input())
	if n == 1:
		leng = []
		addi = []
		sub = []
		for i in range(n):
			temp = list(map(int, input().split()))
			leng = temp[1:]
			for i in range(len(leng)):
				if leng[i] > 0:
					addi.append(leng[i])
				else:
					sub.append(leng[i])
		print(len(addi) * len(sub))
	else:
		dicti = {}
		l = []
		for i in range(n):
			Mi = list(map(int, input().split()))
			posi = 0
			for j in range(Mi[0]):
				if Mi[j + 1] < 0:
					ck = 1
					posi = j + 1
				if Mi[j + 1] > 0:
					nv = 1
				else:
					nv = -1
				temp = [i, nv]
				if abs(Mi[j + 1]) in dicti:
					dicti[abs(Mi[j + 1])].append(temp)
				else:
					dicti[abs(Mi[j + 1])] = []
					dicti[abs(Mi[j + 1])].append(temp)
			Mi.append(posi)
			l.append(Mi)
		dynam = {}
		for (ke, va) in sorted(dicti.items()):
			dynam[ke] = va
		countt = 0
		for i in dynam:
			le = len(dynam[i])
			if le == 0:
				continue
			elif le > 1:
				for j in range(le):
					tep = l[dynam[i][j][0]][-1]
					if dynam[i][j][1] == -1:
						l[dynam[i][j][0]].pop(tep)
						l[dynam[i][j][0]][-1] -= 1
						countt += l[dynam[i][j][0]][-1]
						l[dynam[i][j][0]][0] -= 1
					else:
						l[dynam[i][j][0]].pop(tep + 1)
						l[dynam[i][j][0]][0] -= 1
						countt += l[dynam[i][j][0]][0] - l[dynam[i][j][0]][-1]
				countt += 1
			else:
				tep = l[dynam[i][0][0]][-1]
				if dynam[i][0][1] == -1:
					countt += l[dynam[i][0][0]][0] - l[dynam[i][0][0]][-1]
					l[dynam[i][0][0]].pop(tep)
					l[dynam[i][0][0]][-1] -= 1
					l[dynam[i][0][0]][0] -= 1
				else:
					countt += l[dynam[i][0][0]][-1]
					l[dynam[i][0][0]].pop(tep + 1)
					l[dynam[i][0][0]][0] -= 1
		print(countt)


t = int(input())
for _ in range(t):
	n = int(input())
	if n == 1:
		le = []
		plus = []
		minu = []
		for i in range(n):
			temp = list(map(int, input().split()))
			le = temp[1:]
			for i in range(len(le)):
				if le[i] > 0:
					plus.append(le[i])
				else:
					minu.append(le[i])
		print(len(plus) * len(minu))
	else:
		dic = {}
		l = []
		for i in range(n):
			M = list(map(int, input().split()))
			pos = 0
			for j in range(M[0]):
				if M[j + 1] < 0:
					ck = 1
					pos = j + 1
				if M[j + 1] > 0:
					nv = 1
				else:
					nv = -1
				temp = [i, nv]
				if abs(M[j + 1]) in dic:
					dic[abs(M[j + 1])].append(temp)
				else:
					dic[abs(M[j + 1])] = []
					dic[abs(M[j + 1])].append(temp)
			M.append(pos)
			l.append(M)
		dp = {}
		for (k, v) in sorted(dic.items()):
			dp[k] = v
		cnt = 0
		for i in dp:
			le = len(dp[i])
			if le == 0:
				continue
			elif le > 1:
				for j in range(le):
					kk = l[dp[i][j][0]][-1]
					if dp[i][j][1] == -1:
						l[dp[i][j][0]].pop(kk)
						l[dp[i][j][0]][-1] -= 1
						cnt += l[dp[i][j][0]][-1]
						l[dp[i][j][0]][0] -= 1
					else:
						l[dp[i][j][0]].pop(kk + 1)
						l[dp[i][j][0]][0] -= 1
						cnt += l[dp[i][j][0]][0] - l[dp[i][j][0]][-1]
				cnt += 1
			else:
				kk = l[dp[i][0][0]][-1]
				if dp[i][0][1] == -1:
					cnt += l[dp[i][0][0]][0] - l[dp[i][0][0]][-1]
					l[dp[i][0][0]].pop(kk)
					l[dp[i][0][0]][-1] -= 1
					l[dp[i][0][0]][0] -= 1
				else:
					cnt += l[dp[i][0][0]][-1]
					l[dp[i][0][0]].pop(kk + 1)
					l[dp[i][0][0]][0] -= 1
		print(cnt)


from sys import stdin, stdout
from bisect import bisect_left, bisect_right
for _ in range(int(stdin.readline())):
	n = int(stdin.readline())
	di = {}
	orig = {}
	abtmpj = 0
	temp = 0
	for i in range(n):
		tmp = list(map(int, stdin.readline().split()))
		m = tmp[0]
		tmp = tmp[1:]
		for j in range(0, m):
			abtmpj = abs(tmp[j])
			if abtmpj not in di:
				if tmp[j] > 0:
					di[abtmpj] = bisect_left(tmp, -abtmpj)
					orig[abtmpj] = m - j - 1
				else:
					temp = bisect_left(tmp, abtmpj)
					if temp < m and tmp[temp] == abtmpj:
						di[abtmpj] = -1
					else:
						di[abtmpj] = m - temp
					orig[abtmpj] = j
			else:
				if tmp[j] > 0:
					orig[abtmpj] += m - j - 1
				else:
					orig[abtmpj] += j
				di[abtmpj] = orig[abtmpj] + 1
	ans = 0
	for k in di:
		ans += di[k]
	print(ans)


def get_line_input():
	return map(int, input().split())
tests = int(input())
while tests:
	tests -= 1
	n = int(input())
	c = []
	a = []
	for i in range(n):
		(m, *x) = get_line_input()
		neg = 0
		for p in x:
			neg += p < 0
			a.append((abs(p), i, p > 0))
		c.append([neg, m - neg])
	ans = 0
	a.sort(reverse=True)
	while len(a) > 0:
		origin = []
		p = a[-1][0]
		while len(a) > 0 and p == a[-1][0]:
			origin.append(a.pop())
		if len(origin) == 1:
			(_, line, flag) = origin[0]
			c[line][flag] -= 1
			ans += c[line][not flag]
		else:
			for (_, line, flag) in origin:
				c[line][flag] -= 1
				ans += c[line][flag]
			ans += 1
	print(ans)


from collections import Counter
t = int(input())
while t:
	t -= 1
	n = int(input())
	mat = []
	noa = []
	coun = Counter()
	for i in range(n):
		x = list(map(int, input().split()))
		noa.append(x[0])
		x = x[1:]
		mat.append(x)
		coun.update(x)
	finalans = 0
	for z in range(n):
		a = mat[z]
		a.sort()
		j = 0
		ll = noa[z]
		while j < ll:
			if a[j] > 0:
				break
			j += 1
		x = a[0:j]
		lx = j
		y = a[j:]
		ly = noa[z] - j
		x.reverse()
		kx = 0
		ky = 0
		i = 0
		j = 0
		while True:
			if i >= lx and j >= ly:
				break
			elif i >= lx or j >= ly:
				if i >= lx:
					if coun[y[j]] + coun[-1 * y[j]] > 1:
						finalans = finalans + ly - j - 1
						j += 1
					else:
						j += 1
				elif coun[x[i]] + coun[-1 * x[i]] > 1:
					finalans = finalans + lx - i - 1
					i += 1
				else:
					i += 1
			elif x[i] == -1 * y[j]:
				finalans = finalans + lx - i - 1 + ly - j - 1
				i += 1
				j += 1
			elif y[j] > -1 * x[i]:
				if coun[x[i]] + coun[-1 * x[i]] > 1:
					finalans = finalans + lx - i - 1
					i += 1
				else:
					finalans = finalans + ly - j
					i += 1
			elif y[j] < -1 * x[i]:
				if coun[y[j]] + coun[-1 * y[j]] > 1:
					finalans = finalans + ly - j - 1
					j += 1
				else:
					finalans = finalans + lx - i
					j += 1
	count = Counter()
	for (keys, items) in coun.items():
		if keys < 0:
			m = coun[keys]
			keys = -1 * keys
			count.update({keys: m})
		else:
			count.update({keys: coun[keys]})
	for (keys, items) in count.items():
		if items > 1:
			finalans += 1
	print(finalans)


for _ in range(int(input())):
	n = int(input())
	lines = {}
	(plus, minus) = ([0] * n, [0] * n)
	for line in range(n):
		for x in list(map(int, input().split()))[1:]:
			if x > 0:
				plus[line] += 1
				if x in lines:
					lines[x][0].append(line)
				else:
					lines[x] = [[line], []]
			else:
				minus[line] += 1
				if -x in lines:
					lines[-x][1].append(line)
				else:
					lines[-x] = [[], [line]]
	answer = 0
	for key in sorted(lines):
		if len(lines[key][0]) + len(lines[key][1]) > 1:
			answer += 1
			for pos in lines[key][0]:
				plus[pos] -= 1
				answer += plus[pos]
			for neg in lines[key][1]:
				minus[neg] -= 1
				answer += minus[neg]
		elif len(lines[key][0]):
			plus[lines[key][0][0]] -= 1
			answer += minus[lines[key][0][0]]
		else:
			minus[lines[key][1][0]] -= 1
			answer += plus[lines[key][1][0]]
	print(answer)


from math import log2
import bisect
from bisect import bisect_left, bisect_right
import sys
sys.setrecursionlimit(10 ** 7)
from collections import defaultdict
inf = float('inf')
for _ in range(int(input())):
	n = int(input())
	matrix = []
	matrix_rev = []
	matrix_containing_dictionary = []
	dict = defaultdict(int)
	distance = defaultdict(int)
	index = defaultdict(set)
	answer = 0
	for i in range(n):
		l = list(map(int, input().split()))
		m = l[0]
		l.remove(l[0])
		matrix.append(l)
		matrix_rev.append([])
		matrix_containing_dictionary.append(defaultdict(int))
		for res in reversed(l):
			matrix_containing_dictionary[-1][res] = 1
			matrix_rev[-1].append(-res)
		t1 = 0
		t2 = 0
		for j in l:
			index[j].add(i)
			if j > 0:
				t1 += 1
				dict[j] += 1
				distance[j] += 1
			else:
				t2 += 1
				dict[j] += 1
				distance[-j] += 1
		answer += t1 * t2
	dict_copy = dict.copy()
	for i in dict:
		if dict_copy[i] + dict_copy[-i] > 1 and i > 0:
			for j in index[i]:
				index_got = bisect_right(matrix[j], i)
				answer += len(matrix[j]) - index_got
				index_got = bisect_right(matrix_rev[j], i)
				answer -= len(matrix[j]) - index_got
		if dict_copy[i] + dict_copy[-i] > 1 and i < 0:
			for j in index[i]:
				index_got = bisect_right(matrix[j], -i)
				answer -= len(matrix[j]) - index_got
				index_got = bisect_right(matrix_rev[j], -i)
				answer += len(matrix[j]) - index_got
	count = 0
	for j in distance:
		if distance[j] > 1:
			answer += 1
			for indices in index[j]:
				if j in matrix_containing_dictionary[indices] and -j in matrix_containing_dictionary[indices]:
					count += 1
	print(answer - count)


from bisect import bisect
from collections import Counter

def ant_collisions(lines):
	c = Counter()
	for line in lines:
		c.update([abs(val) for val in line])
	collision_times = {val for val in c if c[val] > 1}
	collisions = len(collision_times)
	for line in lines:
		rightward = 0
		leftward = 0
		j = bisect(line, 0)
		i = j - 1
		while i >= 0 or j < len(line):
			neg_val = None
			pos_val = None
			if i >= 0:
				neg_val = line[i]
				if neg_val >= 0:
					raise Exception
			if j < len(line):
				pos_val = line[j]
				if pos_val <= 0:
					raise Exception
			if neg_val is None:
				vals = [pos_val]
			elif pos_val is None:
				vals = [neg_val]
			elif abs(neg_val) < pos_val:
				vals = [neg_val]
			elif abs(neg_val) > pos_val:
				vals = [pos_val]
			else:
				if abs(neg_val) != pos_val:
					raise Exception
				vals = [neg_val, pos_val]
			for val in vals:
				if val < 0:
					collisions += leftward
				else:
					collisions += rightward
			for val in vals:
				if abs(val) in collision_times:
					if val < 0:
						leftward += 1
					else:
						rightward += 1
				elif val < 0:
					rightward += 1
				else:
					leftward += 1
			for val in vals:
				if val < 0:
					i -= 1
				else:
					j += 1
	return collisions
T = int(input())
for _ in range(T):
	N = int(input())
	lines = []
	for _ in range(N):
		(M, *X) = list(map(int, input().split()))
		lines.append(X)
	print(ant_collisions(lines))


from collections import defaultdict

def getIndex(A, val, leng):
	(l, r) = (0, leng)
	m = (r + l) // 2
	while l < r:
		m = (r + l) // 2
		if A[m] == val:
			while m + 1 < leng and A[m + 1] == val:
				m += 1
			break
		elif val < A[m]:
			r = m
		else:
			l = m + 1
	while m > -1 and A[m] > val:
		m -= 1
	return m + 1
T = int(input())
for _ in range(T):
	N = int(input())
	another = defaultdict(list)
	myans = 0
	for i in range(N):
		A = list(map(int, input().split()))
		lene = A[0]
		A = A[1:]
		get_all = defaultdict(bool)
		for a in A:
			get_all[a] = True
		for (a, this) in enumerate(A):
			if this < 0:
				ind = getIndex(A, -this, lene)
				another[-this] += [[a, lene - ind]]
			else:
				ind = getIndex(A, -this, lene)
				if get_all[-this] == True:
					another[this] += [[lene - a - 1, ind - 1]]
				else:
					another[this] += [[lene - a - 1, ind]]
	for i in another:
		if len(another[i]) == 1:
			myans += another[i][0][1]
		elif len(another[i]) > 1:
			myans += 1
			for a in another[i]:
				myans += a[0]
	print(myans)


for _ in range(int(input())):
	n = int(input())
	li = []
	for i in range(n):
		p = list(map(int, input().split()))
		li.append(p)
	if n == 1:
		(pos, neg) = (0, 0)
		for i in range(1, li[0][0] + 1):
			if li[0][i] >= 0:
				pos += 1
			else:
				neg += 1
		print(pos * neg)
	else:
		ans = 0
		dict = {}
		pos_neg_cou = []
		for i in range(n):
			p = [0, 0]
			for j in range(1, li[i][0] + 1):
				if li[i][j] >= 0:
					p[0] += 1
				else:
					p[1] += 1
			pos_neg_cou.append(p)
		for i in range(n):
			for j in range(1, li[i][0] + 1):
				if dict.get(li[i][j]) == None:
					dict[li[i][j]] = 1
					dict[-li[i][j]] = 0
				else:
					dict[li[i][j]] += 1
		k = set((abs(i) for i in dict.keys()))
		for i in k:
			if dict[i] + dict[-i] > 1:
				ans += 1
		for i in range(n):
			negs = pos_neg_cou[i][1]
			pos = li[i][0] - pos_neg_cou[i][0] + 1
			while negs > 0 and pos <= li[i][0]:
				if abs(li[i][negs]) >= li[i][pos]:
					if dict[li[i][pos]] + dict[-li[i][pos]] <= 1:
						ans += negs
					else:
						ans += li[i][0] - pos
					pos += 1
				else:
					if dict[li[i][negs]] + dict[-li[i][negs]] <= 1:
						ans += li[i][0] - pos + 1
					else:
						ans += negs - 1
					negs -= 1
			while negs > 0:
				if dict[li[i][negs]] + dict[-li[i][negs]] <= 1:
					ans += li[i][0] - pos + 1
				else:
					ans += negs - 1
				negs -= 1
			while pos <= li[i][0]:
				if dict[li[i][pos]] + dict[-li[i][pos]] <= 1:
					ans += negs
				else:
					ans += li[i][0] - pos
				pos += 1
		print(ans)


N = int(200000.0 + 10)
v = [[] for i in range(2 * N)]

def last(i, low, high, x, n):
	if high >= low:
		mid = low + (high - low) // 2
		if (mid == n - 1 or x < v[i][mid + 1]) and v[i][mid] == x:
			return mid
		elif x < v[i][mid]:
			return last(i, low, mid - 1, x, n)
		else:
			return last(i, mid + 1, high, x, n)
	return low - 1

def mod_upper_bound(i, x):
	return len(v[i]) - (last(i, 0, len(v[i]) - 1, x, len(v[i])) + 1)

def ants():
	ans = 0
	n = int(input())
	Map = dict()
	for i in range(1, n + 1):
		m = list(map(int, input().split()))
		v[i] = []
		v[i + N] = []
		for j in range(1, m[0] + 1):
			if m[j] < 0:
				v[i].append(-m[j])
				if -m[j] not in Map.keys():
					Map[-m[j]] = []
				Map[-m[j]].append(i)
			else:
				v[i + N].append(m[j])
				if m[j] not in Map.keys():
					Map[m[j]] = []
				Map[m[j]].append(i + N)
		v[i].reverse()
	for a in Map:
		b = Map[a]
		if len(b) > 1:
			ans += 1
			for c in b:
				ans += mod_upper_bound(c, a)
		else:
			c = b[0]
			if c > n:
				c -= N
			else:
				c += N
			ans += mod_upper_bound(c, a)
	print(ans)
for i in range(int(input())):
	ants()


def countGreater(arr, l, r, x):
	while l <= r:
		mid = l + (r - l) // 2
		if arr[mid] == x:
			return mid
		elif arr[mid] < x:
			l = mid + 1
		else:
			r = mid - 1
	return -1

def countlesser(arr, k):
	k = k * -1
	if k > 0:
		return len(arr) - index(arr, k)
	else:
		return index(arr, k)

def index(arr, k):
	l = -1
	r = len(arr)
	while l + 1 < r:
		m = l + r >> 1
		if arr[m] >= k:
			r = m
		else:
			l = m
	return r
t = int(input())
for _ in range(t):
	arr = []
	d = {}
	res = 0
	n = int(input())
	if n == 1:
		(m, *arr) = map(int, input().split())
		(count1, count2) = (0, 0)
		for i in range(m):
			if arr[i] > 0:
				count1 += 1
			else:
				count2 += 1
		print(count1 * count2)
		continue
	for i in range(n):
		(m, *temp) = map(int, input().split())
		for j in range(m):
			x = abs(temp[j])
			if x in d:
				d[x] += 1
			else:
				d[x] = 1
		arr.append(temp)
	for i in d.keys():
		if d[i] > 1:
			res += 1
	for i in range(n):
		temp = arr[i].copy()
		for j in range(len(arr[i])):
			h = arr[i][j]
			x = abs(h)
			if d[x] > 1:
				if h > 0:
					res += len(temp) - countGreater(temp, 0, len(temp) - 1, h) - 1
				else:
					res += countGreater(temp, 0, len(temp), h)
			elif d[x] == 1:
				res += countlesser(temp, h)
	print(res)


from collections import defaultdict
import bisect

def lower(lst, num):
	ans = bisect.bisect_left(lst, num)
	if ans == -1:
		return len(lst)
	else:
		return ans

def upper(lst, num):
	ans = bisect.bisect_right(lst, num)
	if ans == -1:
		return len(lst)
	else:
		return ans

def nino():
	n = int(input())
	mp = defaultdict(int)
	ant = []
	for _ in range(n):
		ant.append([int(i) for i in input().split()][1:])
	for i in ant:
		for x in i:
			mp[abs(x)] += 1
	ans = 0
	xp = 0
	for x in mp:
		if mp[x] > 1:
			xp += 1
	for i in range(n):
		for j in range(len(ant[i])):
			curr = 0
			if mp[abs(ant[i][j])] > 1:
				if ant[i][j] > 0:
					curr = len(ant[i]) - (j + 1)
				else:
					curr = j
			elif ant[i][j] > 0:
				curr = lower(ant[i], -1 * ant[i][j])
			else:
				curr = len(ant[i]) - upper(ant[i], -1 * ant[i][j])
			ans += curr
	print(ans + xp)
t = int(input())
for _ in range(t):
	nino()


from collections import defaultdict
from bisect import bisect
for _ in range(int(input())):
	n = int(input())
	d = defaultdict(int)
	li = []
	for _ in range(n):
		l = list(map(int, input().split()))
		for i in l[1:]:
			d[abs(i)] += 1
		li.append(l[1:])
	total_count = 0
	for i in range(n):
		arr = li[i]
		arr_pos = []
		arr_neg = []
		for j in arr:
			if j < 0:
				arr_neg.append(-j)
			else:
				arr_pos.append(j)
		arr_pos.sort()
		arr_neg.sort()
		for j in range(len(arr_pos)):
			if d[arr_pos[j]] > 1:
				total_count += len(arr_pos) - j - 1
			else:
				total_count += len(arr_neg) - bisect(arr_neg, arr_pos[j])
		for j in range(len(arr_neg)):
			if d[arr_neg[j]] > 1:
				total_count += len(arr_neg) - j - 1
			else:
				total_count += len(arr_pos) - bisect(arr_pos, arr_neg[j])
	origin_collide = 0
	for v in d.values():
		if v > 1:
			origin_collide += 1
	print(origin_collide + total_count)


from collections import defaultdict
from bisect import bisect_left, bisect_right
t = int(input())
while t:
	t -= 1
	n = int(input())
	frq = defaultdict(int)
	mat = []
	for i in range(n):
		lis = list(map(int, input().split()))
		lis = lis[1:]
		for j in lis:
			if j < 0:
				frq[abs(j)] += 1
			else:
				frq[j] += 1
		mat.append(lis)
	ans = 0
	for e in frq.values():
		if e > 1:
			ans += 1
	for i in range(n):
		l = len(mat[i])
		pos = 0
		neg = 0
		for j in mat[i]:
			if j < 0:
				if frq[abs(j)] > 1:
					ans += neg
				else:
					idx = bisect_left(mat[i], abs(j))
					ans += l - idx
				neg += 1
			else:
				break
		for j in range(l - 1, -1, -1):
			k = mat[i][j]
			if k > 0:
				if frq[k] > 1:
					ans += pos
				else:
					idx = bisect_left(mat[i], -k)
					ans += idx
				pos += 1
			else:
				break
	print(ans)


t = int(input())
for j in range(0, t):
	n = int(input())
	p = []
	c = []
	d = {}
	co = 0
	if n == 1:
		l = list(map(int, input().split()))
		for k in range(1, len(l)):
			if l[k] > 0:
				print((k - 1) * (l[0] - k + 1))
				break
	else:
		for k in range(0, n):
			l = list(map(int, input().split()))
			h = []
			h = l[1:]
			op1 = []
			op2 = []
			for kk in range(0, l[0]):
				if h[kk] < 0:
					op1.append(h[kk])
					if h[kk] in d:
						d[h[kk]] += 1
					else:
						d[h[kk]] = 1
				else:
					op2.append(h[kk])
					if h[kk] in d:
						d[h[kk]] += 1
					else:
						d[h[kk]] = 1
			h = []
			op1.reverse()
			h.append(op1)
			h.append(op2)
			p.append(h)
		for k in range(0, n):
			while len(p[k][0]) > 0 or len(p[k][1]) > 0:
				if len(p[k][0]) > 0 and len(p[k][1]) > 0:
					if abs(p[k][0][0]) == p[k][1][0]:
						co += len(p[k][0]) + len(p[k][1]) - 2
						p[k][0].pop(0)
						p[k][1].pop(0)
					elif abs(p[k][0][0]) < p[k][1][0]:
						ppo = 0
						if -1 * p[k][0][0] in d:
							ppo = d[p[k][0][0]] + d[-1 * p[k][0][0]]
						else:
							ppo = d[p[k][0][0]]
						if ppo > 1:
							co += len(p[k][0]) - 1
							p[k][0].pop(0)
						else:
							co += len(p[k][1])
							p[k][0].pop(0)
					else:
						ppo = 0
						if -1 * p[k][1][0] in d:
							ppo = d[p[k][1][0]] + d[-1 * p[k][1][0]]
						else:
							ppo = d[p[k][1][0]]
						if ppo > 1:
							co += len(p[k][1]) - 1
							p[k][1].pop(0)
						else:
							co += len(p[k][0])
							p[k][1].pop(0)
				elif len(p[k][0]) > 0:
					ppo = 0
					if -1 * p[k][0][0] in d:
						ppo = d[p[k][0][0]] + d[-1 * p[k][0][0]]
					else:
						ppo = d[p[k][0][0]]
					if ppo > 1:
						co += len(p[k][0]) - 1
					p[k][0].pop(0)
				elif len(p[k][1]) > 0:
					ppo = 0
					if -1 * p[k][1][0] in d:
						ppo = d[p[k][1][0]] + d[-1 * p[k][1][0]]
					else:
						ppo = d[p[k][1][0]]
					if ppo > 1:
						co += len(p[k][1]) - 1
					p[k][1].pop(0)
		cc = 0
		for ii in d:
			if d[ii] == 1:
				if -1 * ii in d:
					if d[-1 * ii] + d[ii] > 1:
						d[-1 * ii] = 1
						d[ii] = 0
						cc += 1
			else:
				if -1 * ii in d:
					d[-1 * ii] = 1
				d[ii] = 0
				cc += 1
		print(co + cc)


def upperbound(arr, low, high, X):
	if low > high:
		return low
	mid = int(low + (high - low) / 2)
	if arr[mid] >= X:
		return upperbound(arr, low, mid - 1, X)
	return upperbound(arr, mid + 1, high, X)

def lowerbound(arr, low, high, X):
	if low > high:
		return low
	mid = int(low + (high - low) / 2)
	if arr[mid] <= X:
		return lowerbound(arr, mid + 1, high, X)
	return lowerbound(arr, low, mid - 1, X)

def solve(dic, arr, n):
	ans = 0
	ax = 0
	for i in dic:
		if dic[i] > 1:
			ax = ax + 1
	for i in range(n):
		for j in range(0, len(arr[i])):
			curr = 0
			if dic[abs(arr[i][j])] > 1:
				if arr[i][j] > 0:
					curr = len(arr[i]) - (j + 1)
				else:
					curr = j
			elif arr[i][j] > 0:
				curr = upperbound(arr[i], 0, len(arr[i]) - 1, -1 * arr[i][j]) - 0
			else:
				curr = len(arr[i]) - (lowerbound(arr[i], 0, len(arr[i]) - 1, -1 * arr[i][j]) - 0)
			ans = ans + curr
	print(ans + ax)

def main():
	for i in range(int(input())):
		n = int(input())
		arr = []
		dic = {}
		for i in range(n):
			ll = list(map(int, input().split()))
			for j in range(1, len(ll)):
				try:
					dic[abs(ll[j])] += 1
				except KeyError:
					dic[abs(ll[j])] = 1
			ll = ll[1:]
			ll.sort()
			arr.append(ll)
		solve(dic, arr, n)
main()


from bisect import bisect_left as bl
from bisect import bisect_right as br
t = int(input())
for _ in range(t):
	n = int(input())
	d = dict()
	mat = []
	for i in range(n):
		l = list(map(int, input().split()))[1:]
		l.sort()
		mat.append(l)
		for j in l:
			if abs(j) in d:
				d[abs(j)] += 1
			else:
				d[abs(j)] = 1
	out = sub = 0
	for i in d:
		if d[i] > 1:
			sub += 1
	for i in range(n):
		for j in range(len(mat[i])):
			cur = 0
			if d[abs(mat[i][j])] > 1:
				if mat[i][j] > 0:
					cur = len(mat[i]) - (j + 1)
				else:
					cur = j
			elif mat[i][j] > 0:
				cur = bl(mat[i], mat[i][j] * -1)
			else:
				cur = len(mat[i]) - br(mat[i], mat[i][j] * -1)
			out += cur
	print(out + sub)


import sys

def get_values():
	return list(map(int, sys.stdin.readline().strip().split()))

def OneLine():
	M = get_values()
	countPos = 0
	countNeg = 0
	for i in range(1, M[0] + 1):
		if M[i] < 0:
			countNeg += 1
		else:
			countPos += 1
	return countNeg * countPos

def Solve(N):
	ants = []
	totalAnts = 0
	num = []
	for line in range(N):
		countPos = 0
		countNeg = 0
		M = get_values()
		for i in range(1, M[0] + 1):
			totalAnts += 1
			if M[i] < 0:
				ants.append([abs(M[i]), 0, line])
				countNeg += 1
			else:
				ants.append([abs(M[i]), 1, line])
				countPos += 1
		num.append([countNeg, countPos])
	M = []
	ants.sort()
	collision = 0
	i = 0
	while i < totalAnts:
		j = i + 1
		while j < totalAnts and ants[j][0] == ants[i][0]:
			j += 1
		if j - i > 1:
			collision += 1
			for k in range(i, j):
				collision += num[ants[k][2]][ants[k][1]] - 1
				num[ants[k][2]][ants[k][1]] -= 1
		else:
			collision += num[ants[i][2]][int(not ants[i][1])]
			num[ants[i][2]][ants[i][1]] -= 1
		i = j
	return collision
test = int(input())
for t in range(test):
	N = int(input())
	if N == 1:
		print(OneLine())
	else:
		print(Solve(N))


def count():
	for i in range(n):
		for j in m[i][1:]:
			try:
				d[abs(j)] += 1
			except:
				d[abs(j)] = 1

def v_(x_p, x_n):
	return x_p * x_n

def solve(a, b):
	(v1, v2) = (len(a), len(b))
	(i, j) = (0, 0)
	value = 0
	while i < len(a) and j < len(b):
		c = 0
		if a[i] > b[j]:
			while j < len(b) and a[i] > b[j]:
				if d[b[j]] > 1:
					value += v2 - 1
				else:
					c += 1
				(v2, j) = (v2 - 1, j + 1)
			value += v_(v1, c)
		elif a[i] < b[j]:
			while i < len(a) and a[i] < b[j]:
				if d[a[i]] > 1:
					value += v1 - 1
				else:
					c += 1
				(v1, i) = (v1 - 1, i + 1)
			value += v_(c, v2)
		else:
			(v1, v2) = (v1 - 1, v2 - 1)
			value += v1 + v2
			(i, j) = (i + 1, j + 1)
	while i < len(a):
		if v2 > 0:
			(v1, v2) = (v1 - 1, v2 - 1)
			value += v1 + v2 + 1
			if d[a[i]] > 1:
				value += v1 + v2
		else:
			v1 -= 1
			if d[a[i]] > 1:
				value += v1
		i += 1
	while j < len(b):
		if v1 > 0:
			(v1, v2) = (v1 - 1, v2 - 1)
			value += v1 + v2 + 1
			if d[b[j]] > 1:
				value += v1 + v2
		else:
			v2 -= 1
			if d[b[j]] > 1:
				value += v2
		j += 1
	return value

def answer():
	ans = 0
	for i in d.values():
		if i > 1:
			ans += 1
	for i in range(n):
		(ap, an) = ([], [])
		for j in m[i][1:]:
			if j > 0:
				ap.append(j)
			else:
				an.append(-j)
		ans += solve(ap, an[::-1])
	return ans
for T in range(int(input())):
	n = int(input())
	m = [list(map(int, input().split())) for i in range(n)]
	d = dict()
	count()
	print(answer())


from collections import defaultdict
for y in range(int(input())):
	d = defaultdict(list)
	n = int(input())
	arr = []
	for i in range(n):
		(a, *lst) = map(int, input().split())
		p = n = 0
		for j in range(a):
			if lst[j] > 0:
				p += 1
				d[lst[j]].append(i + 1)
			else:
				n += 1
				d[-1 * lst[j]].append(-1 * (i + 1))
		arr.append([p, n])
	ans = 0
	for i in sorted(d):
		if len(d[i]) == 1:
			temp = d[i][0]
			if temp > 0:
				temp -= 1
				ans += arr[temp][1]
				arr[temp][0] -= 1
			else:
				temp = temp * -1
				temp -= 1
				ans += arr[temp][0]
				arr[temp][1] -= 1
		else:
			ans += 1
			for j in d[i]:
				if j > 0:
					temp = j
					temp -= 1
					arr[temp][0] -= 1
					ans += arr[temp][0]
				else:
					temp = -1 * j
					temp -= 1
					arr[temp][1] -= 1
					ans += arr[temp][1]
	print(ans)


try:
	from collections import defaultdict
	from bisect import bisect_left, bisect_right
	for ii in range(int(input())):
		n = int(input())
		(x, y, z, hi, lo, d, r) = (0, [], [], 0, 0, defaultdict(int), 0)
		for jj in range(n):
			(a, *b) = list(map(int, input().split()))
			b = list(sorted(b))
			for kk in b:
				d[abs(kk)] += 1
				if d[abs(kk)] == 2:
					x += 1
			y.append(b)
			z.append(a)
		for jj in range(n):
			for kk in range(z[jj]):
				if d[abs(y[jj][kk])] <= 1:
					if y[jj][kk] <= 0:
						x += z[jj] - bisect_right(y[jj], y[jj][kk] * -1)
					else:
						x += bisect_left(y[jj], y[jj][kk] * -1)
				elif y[jj][kk] <= 0:
					x += kk
				else:
					x += z[jj] - kk - 1
		print(x)
except:
	pass


from collections import defaultdict as dd
from bisect import bisect_right as br
for case in range(int(input())):
	N = int(input())
	ants = []
	collisions = dd(list)
	for i in range(N):
		(M, *arr) = map(int, input().split())
		ants.append(arr)
		for it in arr:
			collisions[abs(it)] += [[it, i]]
	total_coll = 0
	for (Time, llis) in collisions.items():
		colls = 0
		if len(llis) > 1:
			colls += 1
			for (ant, line) in llis:
				coll = 0
				ind = br(ants[line], ant)
				if ant < 0:
					coll = ind - 1
				else:
					coll = len(ants[line]) - ind
				colls += coll
		else:
			for (ant, line) in llis:
				coll = 0
				ind = br(ants[line], -ant)
				if ant < 0:
					coll = len(ants[line]) - ind
				else:
					coll = ind
				colls += coll
		total_coll += colls
	print(total_coll)


def lower_bound(a, x):
	lo = -1
	high = len(a)
	while lo + 1 < high:
		mid = lo + high >> 1
		if a[mid] >= x:
			high = mid
		else:
			lo = mid
	return high

def upper_bound(a, x):
	lo = -1
	high = len(a)
	while lo + 1 < high:
		mid = lo + high >> 1
		if a[mid] <= x:
			lo = mid
		else:
			high = mid
	return lo + 1
t = int(input())
for _ in range(t):
	n = int(input())
	X = []
	m = []
	coord = {}
	liy = []
	for it in range(10000):
		liy.append(it)
	lia = []
	for it in range(10000):
		lia.append(it)
	lib = []
	for it in range(10000):
		lib.append(it)
	lic = []
	for it in range(10000):
		lic.append(it)
	lid = []
	for it in range(10000):
		lid.append(it)
	lie = []
	for it in range(10000):
		lie.append(it)
	lif = []
	for it in range(10000):
		lif.append(it)
	for inp in range(n):
		temp1 = list(map(int, input().split()))
		m = temp1[0]
		temp2 = []
		lity = []
		for ui in range(300):
			lity.append(ui)
		for i in range(1, m + 1):
			temp2.append(temp1[i])
			coord[abs(temp1[i])] = coord.get(abs(temp1[i]), 0) + 1
		temp2.sort()
		X.append(temp2)
	origin = 0
	res = 0
	for i in coord:
		if coord[i] > 1:
			origin += 1
	for i in range(0, n):
		for j in range(0, len(X[i])):
			collision = 0
			if coord[abs(X[i][j])] <= 1:
				if X[i][j] > 0:
					collision = lower_bound(X[i], -1 * X[i][j])
				else:
					collision = len(X[i]) - upper_bound(X[i], -1 * X[i][j])
			elif X[i][j] <= 0:
				collision = j
			else:
				collision = len(X[i]) - (j + 1)
			res += collision
	print(res + origin)


t = int(input())
for _ in range(t):
	n = int(input())
	ants = []
	sizes = []
	dictt = {}
	neg = []
	ans = 0
	for itr in range(n):
		temp = list(map(int, input().split()))
		sizes.append(temp[0])
		temp.pop(0)
		ants.append(temp)
		negnum = 0
		tempset = set()
		for i in temp:
			if i < 0:
				negnum += 1
			tempset.add(abs(i))
		neg.append(negnum)
		for i in tempset:
			if i in dictt:
				if dictt[i] == 1:
					dictt[i] = 2
					ans += 1
			else:
				dictt[i] = 1
	for temp in ants:
		cntl = 0
		cntr = 0
		for i in temp:
			if i < 0 and dictt[abs(i)] == 1:
				cntl += 1
			elif i > 0 and dictt[i] == 1:
				cntr += 1
		ans += cntl * cntr
	cnt = []
	for i in range(len(ants)):
		indxxl = neg[i] - 1
		indxxr = neg[i]
		numl = 0
		numr = 0
		for j in range(neg[i] - 1, -1, -1):
			ant = ants[i][j]
			if dictt[abs(ant)] == 2:
				if ant < 0:
					ans += j
					ind = indxxr
					while ind < sizes[i]:
						if ants[i][ind] >= abs(ant):
							break
						if dictt[ants[i][ind]] == 1:
							numr += 1
						ind += 1
					ans += numr
					indxxr = ind
		for j in range(neg[i], sizes[i]):
			ant = ants[i][j]
			if dictt[abs(ant)] == 2:
				if ant > 0:
					ans += sizes[i] - j - 1
					ind = indxxl
					while ind >= 0:
						if abs(ants[i][ind]) >= ant:
							break
						if dictt[abs(ants[i][ind])] == 1:
							numl += 1
						ind -= 1
					ans += numl
					indxxl = ind
	print(ans)


def lb(A, x):
	start = 0
	end = len(A) - 1
	while start < end:
		mid = (start + end) // 2
		if A[mid] < x:
			start = mid + 1
		else:
			end = mid
	if A[start] < x:
		return len(A)
	else:
		return start

def ub(A, x):
	start = 0
	end = len(A) - 1
	while start < end:
		mid = (start + end) // 2
		if A[mid] <= x:
			start = mid + 1
		else:
			end = mid
	if A[start] > x:
		return start
	else:
		return len(A)
T = int(input())
for _ in range(T):
	N = int(input())
	A = []
	D = dict()
	for i in range(N):
		B = [int(x) for x in input().split(' ')]
		M = B[0]
		B = B[1:]
		for j in range(M):
			k = B[j]
			if abs(k) in D.keys():
				D[abs(k)] += 1
			else:
				D[abs(k)] = 1
		A.append(B)
	ans = 0
	for l in D.keys():
		if D[l] > 1:
			ans += 1
	for i in range(N):
		for j in range(len(A[i])):
			ki = 0
			if D[abs(A[i][j])] > 1:
				if A[i][j] < 0:
					ki = j
				else:
					ki = len(A[i]) - j - 1
			elif A[i][j] > 0:
				ki = lb(A[i], -A[i][j])
			else:
				ki = len(A[i]) - ub(A[i], -A[i][j])
			ans += ki
	print(ans)


def opp(arr, target, start, end):
	ans = -1
	while start <= end:
		mid = (start + end) // 2
		if arr[mid] >= target:
			end = mid - 1
		else:
			ans = mid
			start = mid + 1
	return ans

def opn(arr, target, start, end):
	ans = -1
	while start <= end:
		mid = (start + end) // 2
		if arr[mid] <= target:
			start = mid + 1
		else:
			ans = mid
			end = mid - 1
	return ans
from collections import defaultdict
t = int(input())
for _ in range(t):
	ans = 0
	freq = defaultdict(int)
	n = int(input())
	lines = []
	lens = []
	for __ in range(n):
		x = list(map(int, input().split()))
		x.append(10 ** 10)
		for i in range(1, x[0] + 1):
			freq[x[i]] += 1
		lens.append(x[0])
		x[0] = -10 ** 9 - 1
		lines.append(x)
	for i in range(n):
		s = [0] * (lens[i] + 2)
		m = [0] * (lens[i] + 2)
		for j in range(1, lens[i] + 1):
			if freq[lines[i][j]] + freq[-lines[i][j]] == 1:
				s[j] = 1 + s[j - 1]
				m[j] = m[j - 1]
			else:
				m[j] = 1 + m[j - 1]
				s[j] = s[j - 1]
		(s[lens[i] + 1], m[lens[i] + 1]) = (s[lens[i]], m[lens[i]])
		pz = opp(lines[i], 0, 0, lens[i] + 1)
		for j in range(1, lens[i] + 1):
			po = opp(lines[i], -lines[i][j], 0, lens[i] + 1)
			pt = opn(lines[i], -lines[i][j], 0, lens[i] + 1)
			if lines[i][j] > 0:
				if freq[lines[i][j]] + freq[-lines[i][j]] == 1:
					ans += (s[pz] + (m[j - 1] - m[pz]) + m[po]) / 2
				else:
					ans += (m[j - 1] - m[pz] + (lens[i] - j) + (s[pz] - s[pt - 1])) / 2 + 1 / (freq[lines[i][j]] + freq[-lines[i][j]])
			elif freq[lines[i][j]] + freq[-lines[i][j]] == 1:
				ans += (s[lens[i]] - s[pz] + m[pz] - m[j] + m[lens[i]] - m[pt - 1]) / 2
			else:
				ans += (j - 1 + m[pz] - m[j] + s[po] - s[pz]) / 2 + 1 / (freq[lines[i][j]] + freq[-lines[i][j]])
	print(round(ans))


import sys
input = sys.stdin.readline

def check(p, i, j, v):
	if i > j:
		return i
	m = (i + j) // 2
	if p[m] > v:
		return check(p, i, m - 1, v)
	else:
		return check(p, m + 1, j, v)

def check2(p, i, j, v):
	if i > j:
		return i
	m = (i + j) // 2
	if abs(p[m]) > v:
		return check2(p, m + 1, j, v)
	else:
		return check2(p, i, m - 1, v)
t = int(input())
for _ in range(t):
	n = int(input())
	if n == 1:
		l = []
		for i in range(n):
			l.append(list(map(int, input().split())))
		if n == 1:
			x = set()
			p = l[0]
			m = p[0]
			p = p[1:]
			l = []
			r = []
			for i in p:
				if i < 0:
					l.append(i)
				else:
					r.append(i)
			print(len(l) * len(r))
		else:
			print(0)
	else:
		l = []
		d = {}
		for i in range(n):
			p = list(map(int, input().split()))
			x = []
			for j in range(1, len(p)):
				x.append(p[j])
				if abs(p[j]) in d.keys():
					d[abs(p[j])] += 1
				else:
					d[abs(p[j])] = 1
			l.append(x)
		ans = 0
		for k in d.keys():
			if d[k] > 1:
				ans += 1
		for el in l:
			for i in range(len(el)):
				if d[abs(el[i])] > 1:
					if el[i] < 0:
						ans += i
					else:
						ans += len(el) - i - 1
				elif el[i] < 0:
					ct = len(el) - check(el, i + 1, len(el) - 1, abs(el[i]))
					ans += ct
				else:
					ct = check2(el, 0, i - 1, el[i])
					ans += ct
		print(ans)


import sys
input = sys.stdin.readline
t = int(input())
for t1 in range(t):
	n = int(input())
	c = 0
	d = {}
	mat = []
	for i in range(n):
		l = list(map(int, input().split(' ')))
		m = l[0]
		l = l[1:]
		a = 0
		mat.append(l)
		for j in range(m):
			d[abs(l[j])] = d.get(abs(l[j]), 0) + 1
	for i in range(n):
		l = mat[i]
		pos = []
		neg = []
		for j in range(len(l)):
			if l[j] < 0:
				neg.append(abs(l[j]))
			else:
				pos.append(abs(l[j]))
		pos = pos[::-1]
		while len(pos) > 0 or len(neg) > 0:
			if len(pos) == 0:
				a = neg[-1]
				if d.get(a, 0) >= 2:
					c += len(neg) - 1
				neg.pop()
			elif len(neg) == 0:
				a = pos[-1]
				if d.get(a, 0) >= 2:
					c += len(pos) - 1
				pos.pop()
			else:
				a = pos[-1]
				b = neg[-1]
				if a < b:
					if d.get(a, 0) < 2:
						c += len(neg)
					else:
						c += len(pos) - 1
					pos.pop()
				elif a > b:
					if d.get(b, 0) < 2:
						c += len(pos)
					else:
						c += len(neg) - 1
					neg.pop()
				else:
					c += len(pos) + len(neg) - 2
					pos.pop()
					neg.pop()
	for i in d:
		if d[i] > 1:
			c += 1
	print(c)


def lin():
	return list(map(int, input().strip().split()))

def special_dictionary(arr1, arr2, common):
	(a, b) = (len(arr1), len(arr2))
	dic1 = {}
	dic2 = {}
	j = 0
	for i in range(a):
		if i > 0:
			dic1[i] = dic1[i - 1]
		else:
			dic1[i] = 0
		while j < b and arr2[j] < arr1[i]:
			if arr2[j] not in common:
				dic1[i] += 1
			j += 1
	j = 0
	for i in range(b):
		if i > 0:
			dic2[i] = dic2[i - 1]
		else:
			dic2[i] = 0
		while j < a and arr1[j] < arr2[i]:
			if arr1[j] not in common:
				dic2[i] += 1
			j += 1
	return (dic1, dic2)
test = int(input().strip())
for _ in range(test):
	n = int(input().strip())
	lines = []
	(se, common) = (set(), set())
	for i in range(n):
		(m, *line) = lin()
		(neg, pos) = ([], [])
		for item in line:
			if abs(item) in se:
				common.add(abs(item))
			else:
				se.add(abs(item))
			if item < 0:
				neg.append(-item)
			else:
				pos.append(item)
		neg.sort()
		pos.sort()
		lines.append((neg, pos))
	collisions = len(common)
	for line in lines:
		(neg, pos) = line
		(l1, l2) = (len(neg), len(pos))
		(dic1, dic2) = special_dictionary(neg, pos, common)
		for i in range(l1):
			if neg[i] in common:
				collisions += l1 - i - 1
				collisions += dic1[i]
		for i in range(l2):
			if pos[i] in common:
				collisions += l2 - i - 1
				collisions += dic2[i]
		(c1, c2) = (l1 - len(set(neg) & common), l2 - len(set(pos) & common))
		collisions += c1 * c2
	print(collisions)


from collections import defaultdict, deque

def read_test():
	n = int(input())
	m = [[int(x) for x in input().strip().split(' ')[1:]] for _ in range(n)]
	return (n, m)

def solve(n, m):
	count = defaultdict(int)
	events = []
	for line in range(n):
		for ant in m[line]:
			orintation = ant >= 0
			events.append((abs(ant), orintation, line))
			count[line, orintation] += 1
	events = deque(sorted(events))
	interactions = 0
	while events:
		ants = [events.popleft()]
		while events and events[0][0] == ants[0][0]:
			ants.append(events.popleft())
		collision = len(ants) > 1
		if not collision:
			(_, o, l) = ants[0]
			interactions += count[l, not o]
			count[l, o] -= 1
			continue
		interactions += 1
		for (_, o, l) in ants:
			count[l, o] -= 1
			interactions += count[l, o]
	return interactions
T = int(input())
for _ in range(T):
	(n, m) = read_test()
	print(solve(n, m))


debug = 0

class Line:

	def __init__(self, m, l):
		self.pos = []
		self.neg = []
		self.negatives = 0
		for i in l:
			if i > 0:
				self.pos.append(i)
			else:
				self.neg.append(-i)
				self.negatives += 1
		self.positives = m - self.negatives
		self.pos.sort()
		self.neg.sort()
		self.collisions = self.positives * self.negatives
		if debug:
			print(self.positives, self.negatives)
			print(self.collisions, 'collisions')

	def record(self, time, change, collisions, one_ant):
		if time in collisions:
			collisions[time] += change
		elif time in one_ant:
			collisions[time] = one_ant[time] + change
		else:
			one_ant[time] = change

	def update_collisions(self, collisions, one_ant):
		i = j = 0
		n = min(self.positives, self.negatives)
		while i < self.positives and j < self.negatives:
			a = self.pos[i]
			b = self.neg[j]
			if a == b:
				if a in collisions:
					collisions[a] -= 1
				elif a in one_ant:
					collisions[a] = one_ant[a] - 1
				else:
					collisions[a] = -1
				i += 1
				j += 1
			elif a < b:
				change = -(self.negatives - j) + self.positives - i - 1
				self.record(a, change, collisions, one_ant)
				i += 1
			else:
				change = -(self.positives - i) + self.negatives - j - 1
				self.record(b, change, collisions, one_ant)
				j += 1
		if i == self.positives:
			while j < self.negatives:
				change = self.negatives - j - 1
				self.record(self.neg[j], change, collisions, one_ant)
				j += 1
		elif j == self.negatives:
			while i < self.positives:
				change = self.positives - i - 1
				self.record(self.pos[i], change, collisions, one_ant)
				i += 1
		else:
			raise Exeption('wtf')
		if debug:
			print('one ant:', one_ant)
			print('collisions', collisions)

def solve(n):
	one_ant = {}
	collisions = {}
	result = 0
	for _ in range(n):
		l = map(int, input().split())
		ants = next(l)
		line = Line(ants, l)
		result += line.collisions
		line.update_collisions(collisions, one_ant)
	for k in collisions:
		result += collisions[k] + 1
	print(result)
for _ in range(int(input())):
	n = int(input())
	solve(n)


from collections import defaultdict
t = int(input())
for _t in range(t):
	n = int(input())
	res = 0
	ant_colony = defaultdict(list)
	blocked_pc = [0] * n
	blocked_nc = [0] * n
	total_pc = [0] * n
	total_nc = [0] * n
	all_pc = [0] * n
	all_nc = [0] * n
	for i in range(n):
		(m, *xs) = list(map(int, input().split()))
		all_nc[i] = 0
		for x in xs:
			if x < 0:
				all_nc[i] += 1
				ant_colony[-x].append((i, 0))
			else:
				ant_colony[x].append((i, 1))
		all_pc[i] = m - all_nc[i]
	total_collision_at_0 = 0
	for abs_val in sorted(ant_colony):
		if len(ant_colony[abs_val]) == 1:
			idx = ant_colony[abs_val][0][0]
			if ant_colony[abs_val][0][1] == 0:
				res += all_pc[idx]
				res += blocked_nc[idx]
				res -= blocked_pc[idx]
				total_nc[idx] += 1
			else:
				res += all_nc[idx]
				res += blocked_pc[idx]
				res -= blocked_nc[idx]
				total_pc[idx] += 1
		else:
			total_collision_at_0 += 1
			for (idx, pnp) in ant_colony[abs_val]:
				if pnp == 0:
					res += total_pc[idx]
					res -= blocked_pc[idx]
					total_nc[idx] += 1
					res += all_nc[idx]
					res -= total_nc[idx]
					res += blocked_nc[idx]
					blocked_nc[idx] += 1
				else:
					res += total_nc[idx]
					res -= blocked_nc[idx]
					total_pc[idx] += 1
					res += all_pc[idx]
					res -= total_pc[idx]
					res += blocked_pc[idx]
					blocked_pc[idx] += 1
	print(total_collision_at_0 + res // 2)


import sys
from bisect import *
from collections import *
input = sys.stdin.readline

def inp():
	return int(input())

def st():
	return input().rstrip('\n')

def lis():
	return list(map(int, input().split()))

def ma():
	return map(int, input().split())
t = inp()
while t:
	t -= 1
	n = inp()
	ha = []
	d = {}
	for i in range(n):
		a = lis()
		a = a[1:]
		ha.append(a)
		for j in range(len(a)):
			try:
				d[abs(a[j])] += 1
			except:
				d[abs(a[j])] = 1
	r = 0
	for i in d.keys():
		r += d[i] > 1
	for i in range(n):
		for j in range(len(ha[i])):
			z = ha[i][j]
			if d[abs(z)] > 1:
				if z < 0:
					r += j
				else:
					r += len(ha[i]) - j - 1
			elif z > 0:
				r += bisect_left(ha[i], -z)
			else:
				r += len(ha[i]) - bisect_right(ha[i], -z)
	print(r)


def solve(ant_dict, N):
	num_collisions = 0
	center_times = dict()
	for i in range(N):
		for ant in ant_dict[i]:
			dist = abs(ant)
			if dist not in center_times:
				center_times[dist] = 0
			if center_times[dist] == 1:
				num_collisions += 1
			center_times[dist] += 1
	for i in range(N):
		num_pos_behind = 0
		num_neg_behind = 0
		prev_ant = 0
		for ant in ant_dict[i]:
			if ant > 0:
				if center_times[abs(ant)] > 1:
					num_collisions += num_pos_behind
				else:
					num_collisions += num_neg_behind
					if abs(ant) == abs(prev_ant):
						num_collisions -= 1
				num_pos_behind += 1
			else:
				if center_times[abs(ant)] > 1:
					num_collisions += num_neg_behind
				else:
					num_collisions += num_pos_behind
					if abs(ant) == abs(prev_ant):
						num_collisions -= 1
				num_neg_behind += 1
	return num_collisions
for _ in range(int(input())):
	N = int(input())
	ant_dict = {i: [] for i in range(N)}
	for i in range(N):
		ant_dict[i] = list(map(int, input().split()))[1:]
		sort_key = lambda x: -x if x > 0 else x + 0.5
		ant_dict[i].sort(key=sort_key)
	print(solve(ant_dict, N))


from collections import defaultdict
for _ in range(int(input())):
	n = int(input())
	(c, a) = ([[0 for _ in range(2)] for _ in range(n)], defaultdict(list))
	for i in range(n):
		for j in list(map(int, input().split()))[1:]:
			if j < 0:
				c[i][0] += 1
				a[-j].append([i, 0])
			else:
				c[i][1] += 1
				a[j].append([i, 1])
	ans = 0
	for i in sorted(a.keys()):
		if len(a[i]) > 1:
			ans += 1
			for j in a[i]:
				c[j[0]][j[1]] -= 1
				ans += c[j[0]][j[1]]
		else:
			c[a[i][0][0]][a[i][0][1]] -= 1
			ans += c[a[i][0][0]][a[i][0][1] ^ 1]
	print(ans)


import base64, codecs
magic = 'ZGVmIGdldGludHMoKToKICAgIHJldHVybiBsaXN0KG1hcChpbnQsIGlucHV0KCkuc3BsaXQoKSkpCgoKVCA9IGludChpbnB1dCgpKQoKZm9yIF8gaW4gcmFuZ2UoVCk6CiAgICBuID0gaW50KGlucHV0KCkpCgogICAgYW50cyA9IFtdCiAgICByZW0gPSBbXQoKICAgIGZvciBpIGluIHJhbmdlKG4pOgogICAgICAgIG0sICpwb3MgPSBnZXRpbnRzKCkKICAgICAgICByZW0uYXBwZW5kKFswLCAwXSkKICAgICAgICBmb'
love = '3VtrPOcovOjo3Z6PvNtVPNtVPNtVPNtVTyzVUttCvNjBtbtVPNtVPNtVPNtVPNtVPNtLJ50pl5upUOyozDbXUtfVTxfVQNcXDbtVPNtVPNtVPNtVPNtVPNtpzIgJl0kKIfjKFNeCFNkPvNtVPNtVPNtVPNtVTIfp2H6PvNtVPNtVPNtVPNtVPNtVPOuoaEmYzSjpTIhMPtbYKtfVTxfVQRcXDbtVPNtVPNtVPNtVPNtVPNtpzIgJl0kKIfkKFNeCFNkPvNtVPOuoaEmYaAipaDbXDbXVPNtVTShplN9VQNXPvNtVPOhK2ShqU'
god = 'MgPSBsZW4oYW50cykKICAgIGkgPSAwCiAgICB3aGlsZSBpIDwgbl9hbnRzOgogICAgICAgIGEgPSBbYW50c1tpXV0KICAgICAgICBpICs9IDEKICAgICAgICB3aGlsZSBpIDwgbl9hbnRzIGFuZCBhbnRzW2ldWzBdID09IGFbMF1bMF06CiAgICAgICAgICAgIGEuYXBwZW5kKGFudHNbaV0pCiAgICAgICAgICAgIGkgKz0gMQogICAgICAgIGlmIGxlbihhKSA+IDE6CiAgICAgICAgICAgIGFucyArPSAxCiAgICAgICA'
destiny = 'tVPNtVTMipvOuoaDtnJ4tLGbXVPNtVPNtVPNtVPNtVPNtVUWyoIguoaEoZI1qJ2ShqSflKI0tYG0tZDbtVPNtVPNtVPNtVPNtVPNtLJ5mVPf9VUWyoIguoaEoZI1qJ2ShqSflKI0XVPNtVPNtVPOyoUAyBtbtVPNtVPNtVPNtVPOuoaDtCFOuJmOqPvNtVPNtVPNtVPNtVUWyoIguoaEoZI1qJ2ShqSflKI0tYG0tZDbtVPNtVPNtVPNtVPOuoaZtXm0tpzIgJ2ShqSfkKI1oZFNgVTShqSflKI0XVPNtVUOlnJ50XTShplxX'
joy = 'rot13'
trust = eval('magic') + eval('codecs.decode(love, joy)') + eval('god') + eval('codecs.decode(destiny, joy)')
eval(compile(base64.b64decode(eval('trust')), '<string>', 'exec'))


for _ in range(int(input())):
	n = int(input())
	ants = []
	count = []
	for i in range(n):
		(m, *x) = map(int, input().strip().split())
		pos = 0
		for p in x:
			pos += int(p > 0)
			ants.append((p, i))
		count.append([pos, m - pos])
	ants.sort(key=lambda x: abs(x[0]), reverse=True)
	collisions = 0
	while len(ants) > 0:
		p = abs(ants[-1][0])
		handle_orgy = []
		while len(ants) > 0 and p == abs(ants[-1][0]):
			handle_orgy.append(ants.pop())
		if len(handle_orgy) > 1:
			for (pos, line) in handle_orgy:
				count[line][pos < 0] -= 1
				collisions += count[line][pos < 0]
			collisions += 1
		else:
			count[handle_orgy[0][1]][handle_orgy[0][0] < 0] -= 1
			collisions += count[handle_orgy[0][1]][handle_orgy[0][0] > 0]
	print(collisions)


t = int(input())
for _ in range(t):
	n = int(input())
	points = []
	stats = []
	for i in range(n):
		a = list(map(int, input().split()))
		j = 1
		x1 = 0
		x2 = 0
		while a[0] >= j:
			if a[j] > 0:
				x = 1
				y = a[j]
				x1 += 1
			else:
				x = 0
				y = a[j] * -1
				x2 += 1
			points.append([y, x, i])
			j += 1
		stats.append([x1, x2])
	points.sort(key=lambda x: x[0])
	i = 0
	j = 0
	ans = 0
	m = len(points)
	while m > i:
		x = points[i][0]
		y = points[i][0]
		while 1:
			j += 1
			if m > j:
				y = points[j][0]
			if x != y or m == j:
				if j - i == 1:
					if points[i][1] == 1:
						ans += stats[points[i][2]][1]
						stats[points[i][2]][0] -= 1
					else:
						ans += stats[points[i][2]][0]
						stats[points[i][2]][1] -= 1
				else:
					ans += 1
					for k in range(i, j):
						if points[k][1] == 1:
							ans += stats[points[k][2]][0] - 1
							stats[points[k][2]][0] = max(stats[points[k][2]][0] - 1, 0)
						else:
							ans += stats[points[k][2]][1] - 1
							stats[points[k][2]][1] = max(stats[points[k][2]][1] - 1, 0)
				break
		i = j
	print(ans)


from collections import defaultdict
import bisect
t = int(input())
for wer in range(t):
	n = int(input())
	di = defaultdict(int)
	li = []
	an = 0
	for i in range(n):
		li1 = list(map(int, input().split()))
		m = li1[0]
		li1 = li1[1:]
		for x in li1:
			di[abs(x)] += 1
		li1.sort()
		li.append(li1)
	for x in di:
		if di[x] > 1:
			an += 1
	for i in range(n):
		for j in range(len(li[i])):
			abc = 0
			if di[abs(li[i][j])] <= 1:
				x = -1 * li[i][j]
				if li[i][j] <= 0:
					abc = len(li[i]) - bisect.bisect_right(li[i], x, 0, len(li[i]))
				else:
					abc = bisect.bisect_left(li[i], x, 0, len(li[i]))
			elif li[i][j] <= 0:
				abc = j
			else:
				abc = len(li[i]) - j - 1
			an += abc
	print(an)


import heapq
from collections import defaultdict
T = int(input())
for _ in range(T):
	N = int(input())
	lines = []
	Ms = []
	n_ants = 0
	for _ in range(N):
		(Mi, *Xs) = [int(i) for i in input().split()]
		n_ants += Mi
		Ms.append(Mi)
		lines.append([-float('inf'), *Xs, float('inf')])
	pp = []
	np = []
	heap = []
	for (line_idx, line) in enumerate(lines):
		for (i, ant) in enumerate(line):
			if ant > 0:
				pp.append(i)
				np.append(i - 1)
				heapq.heappush(heap, (abs(ant), ant > 0, line_idx))
				heapq.heappush(heap, (abs(line[i - 1]), line[i - 1] > 0, line_idx))
				break
	s = sum(((Ms[i] - np[i]) * np[i] for i in range(N)))
	pointers = {True: pp, False: np}
	ant_count = 0
	while ant_count < n_ants:
		(abs_v, sign_v, idx_line) = heap[0]
		pointers[sign_v][idx_line] += 1 if sign_v else -1
		heapq.heapreplace(heap, (abs(lines[idx_line][pointers[sign_v][idx_line]]), sign_v, idx_line))
		ant_count += 1
		if heap[0][0] != abs_v:
			continue
		s += 1
		c_count = defaultdict(int)
		c_count[idx_line] += 1 if sign_v else 2
		while heap[0][0] == abs_v:
			(abs_v, sign_v, idx_line) = heap[0]
			pointers[sign_v][idx_line] += 1 if sign_v else -1
			heapq.heapreplace(heap, (abs(lines[idx_line][pointers[sign_v][idx_line]]), sign_v, idx_line))
			ant_count += 1
			c_count[idx_line] += 1 if sign_v else 2
		for (i, count) in c_count.items():
			if count == 2:
				s -= Ms[i] - pp[i] + 1 - np[i]
			elif count == 1:
				s += Ms[i] - pp[i] + 1 - np[i]
			elif count == 3:
				s -= 1
			else:
				print('WE WILL ROCK YOU')
	print(s)


from collections import defaultdict as dd

def bs(trg, arr, m):
	lo = 0
	hi = m
	while hi - lo > 1:
		mi = (hi + lo) // 2
		if arr[mi] > trg:
			hi = mi
		else:
			lo = mi
	return lo

def solve():
	n = int(input())
	ans = 0
	pants = dd(dict)
	nants = dd(dict)
	nums = set()
	ms = []
	mat = []
	for i in range(n):
		line = list(map(int, input().split()))
		ms.append(line[0])
		ps = set()
		ns = set()
		mat.append(line[1:])
		for (j, num) in enumerate(line[1:]):
			if num > 0:
				pants[num][i] = j
			else:
				nants[-num][i] = j
			nums.add(abs(num))
	nums = sorted(nums)
	for num in nums:
		if len(pants[num]) + len(nants[num]) > 1:
			ans += 1
			for (i, j) in pants[num].items():
				ans += ms[i] - j - 1
			for (i, j) in nants[num].items():
				ans += j
		else:
			for (i, j) in nants[num].items():
				ans += ms[i] - bs(num, mat[i], ms[i]) - 1
			for (i, j) in pants[num].items():
				j = bs(-num, mat[i], ms[i])
				if mat[i][j] <= -num:
					ans += j + 1
	return ans
t = int(input())
for _ in range(t):
	print(solve())


def bos(c, p, s):
	l = len(p)
	for i in range(s, l):
		if p[i] == c:
			return (0, i)
		elif p[i] > c:
			return (l - i, i)
	return (0, l)

def main():
	for cases in range(int(input())):
		n = int(input())
		d = dict()
		for i in range(n):
			k = [int(x) for x in input().split()]
			k = k[1:]
			a = []
			b = []
			for x in k:
				if x > 0:
					a.append(x)
				else:
					b.append(-x)
			b.reverse()
			s = 0
			for j in range(len(a)):
				if a[j] in d:
					d[a[j]][0] = 1
					d[a[j]][2] += len(a) - j - 1
				else:
					d[a[j]] = [0, 0, 0]
					(d[a[j]][1], s) = bos(a[j], b, s)
					d[a[j]][2] = len(a) - j - 1
			s = 0
			for j in range(len(b)):
				if b[j] in d:
					d[b[j]][0] = 1
					d[b[j]][2] += len(b) - j - 1
				else:
					d[b[j]] = [0, 0, 0]
					(d[b[j]][1], s) = bos(b[j], a, s)
					d[b[j]][2] = len(b) - j - 1
		ans = 0
		for i in d.values():
			if i[0] == 0:
				ans += i[1]
			else:
				ans += i[2] + 1
		print(ans)
main()


import sys
T = int(input())
for t in range(T):
	N = int(input())
	M = []
	if N == 1:
		row = list((int(x) for x in input().split()[1:]))
		neg = 0
		pos = 0
		for r in row:
			if r < 0:
				neg += 1
			else:
				pos += 1
		print(int(neg * pos))
	else:
		A_pos = []
		A_neg = []
		total_pos_len = 0
		total_neg_len = 0
		total_collisions = 0
		collision = {}
		pos_lens = []
		neg_lens = []
		pos_collided = []
		neg_collided = []
		for j in range(N):
			row = list((int(x) for x in sys.stdin.readline().strip().split()))
			index = 0
			M = row[0]
			ants = row[1:]
			if ants[0] > 0:
				index = 0
			elif ants[-1] < 0:
				index = M
			else:
				for j in range(M - 1):
					if ants[j] < 0 and ants[j + 1] > 0:
						index = j + 1
						break
			neg_row = ants[:index]
			neg_row.reverse()
			pos_row = ants[index:]
			neg_len = index
			pos_len = M - index
			A_pos.append(pos_row)
			A_neg.append(neg_row)
			total_pos_len += pos_len
			total_neg_len += neg_len
			pos_lens.append(pos_len)
			neg_lens.append(neg_len)
		for a1 in A_pos:
			for a in a1:
				if a in collision.keys():
					collision[a] += 1
				else:
					collision[a] = 1
		for a1 in A_neg:
			for a in a1:
				if -a in collision.keys():
					collision[-a] += 1
				else:
					collision[-a] = 1
		for a in collision.keys():
			if collision[a] > 1:
				total_collisions += 1
		dual_collisions = 0
		for i in range(N):
			i1 = 0
			i2 = 0
			pos_origin_collide = 0
			pos_origin = 0
			neg_origin_collide = 0
			neg_origin = 0
			pos_len = pos_lens[i]
			neg_len = neg_lens[i]
			while i1 < pos_len and i2 < neg_len:
				if A_pos[i][i1] + A_neg[i][i2] < 0:
					if collision[A_pos[i][i1]] > 1:
						dual_collisions += neg_origin - neg_origin_collide
						dual_collisions += pos_origin_collide
						dual_collisions += pos_len - pos_origin - 1
						pos_origin_collide += 1
					else:
						dual_collisions += neg_len - neg_origin_collide
						dual_collisions += pos_origin_collide
					pos_origin += 1
					i1 += 1
				elif A_pos[i][i1] == -A_neg[i][i2]:
					dual_collisions += neg_origin - neg_origin_collide
					dual_collisions += pos_origin - pos_origin_collide
					dual_collisions += pos_origin_collide
					dual_collisions += neg_origin_collide
					dual_collisions += pos_len - pos_origin - 1
					dual_collisions += neg_len - neg_origin - 1
					pos_origin_collide += 1
					pos_origin += 1
					neg_origin += 1
					neg_origin_collide += 1
					i1 += 1
					i2 += 1
				else:
					if collision[-A_neg[i][i2]] > 1:
						dual_collisions += pos_origin - pos_origin_collide
						dual_collisions += neg_origin_collide
						dual_collisions += neg_len - neg_origin - 1
						neg_origin_collide += 1
					else:
						dual_collisions += pos_len - pos_origin_collide
						dual_collisions += neg_origin_collide
					neg_origin += 1
					i2 += 1
			while i1 < pos_len:
				if collision[A_pos[i][i1]] > 1:
					dual_collisions += neg_origin - neg_origin_collide
					dual_collisions += pos_origin_collide
					dual_collisions += pos_len - pos_origin - 1
					pos_origin_collide += 1
				else:
					dual_collisions += neg_len - neg_origin_collide
					dual_collisions += pos_origin_collide
				pos_origin += 1
				i1 += 1
			while i2 < neg_len:
				if collision[-A_neg[i][i2]] > 1:
					dual_collisions += pos_origin - pos_origin_collide
					dual_collisions += neg_origin_collide
					dual_collisions += neg_len - neg_origin - 1
					neg_origin_collide += 1
				else:
					dual_collisions += pos_len - pos_origin_collide
					dual_collisions += neg_origin_collide
				neg_origin += 1
				i2 += 1
		ans = total_collisions + 0.5 * dual_collisions
		print(int(ans))


from collections import defaultdict
for _ in range(int(input())):
	ny = int(input())
	mai_1 = []
	mai_2 = []
	mfqr = defaultdict(lambda : 0)
	moi = []
	for ii_ in range(ny):
		listy = list(map(int, input().split()))
		h = []
		j = []
		moi.append(listy[0])
		for i in range(1, listy[0] + 1):
			mfqr[abs(listy[i])] += 1
			if listy[i] >= 0:
				h.append(listy[i])
			else:
				j.append(abs(listy[i]))
		mai_1.append(h)
		mai_2.append(j[::-1])
	fg = 0
	for i in range(ny):
		(po_x, ne_y) = (0, 0)
		(p, q) = (len(mai_1[i]), len(mai_2[i]))
		(x, y, z, w) = (0, 0, 0, 0)
		(c1, c2, c3, c4) = (0, 0, 0, 0)
		while po_x < p and ne_y < q:
			if mai_1[i][po_x] < mai_2[i][ne_y]:
				if mfqr[mai_1[i][po_x]] > 1:
					for k in range(max(x, 0), p):
						if mai_1[i][k] > mai_1[i][po_x]:
							break
						else:
							c1 += 1
					x = k
					fg += p - c1
					po_x += 1
				else:
					for k in range(max(y, 0), q):
						if mai_2[i][k] > mai_1[i][po_x]:
							break
						else:
							c2 += 1
					y = k
					fg += q - c2
					po_x += 1
			elif mfqr[mai_2[i][ne_y]] > 1:
				for k in range(max(z, 0), q):
					if mai_2[i][k] > mai_2[i][ne_y]:
						break
					else:
						c3 += 1
				z = k
				fg += q - c3
				ne_y += 1
			else:
				for k in range(max(w, 0), p):
					if mai_1[i][k] > mai_2[i][ne_y]:
						break
					else:
						c4 += 1
				w = k
				fg += p - c4
				ne_y += 1
		if ne_y < q:
			for j in range(ne_y, q):
				if mfqr[mai_2[i][j]] == 1:
					continue
				else:
					fg += q - (j + 1)
		if po_x < p:
			for j in range(po_x, p):
				if mfqr[mai_1[i][j]] == 1:
					continue
				else:
					fg += p - (j + 1)
	for i in mfqr.values():
		if i > 1:
			fg += 1
	print(fg)


from collections import Counter

def b_s_n(lst, lst_len):
	(l, h) = (0, lst_len)
	while l < h:
		mid = (l + h) // 2
		if lst[mid] < 0:
			l += 1
		else:
			h = mid
	return l

def b_s(lst, lst_len, l, target):
	if target > lst[lst_len - 1]:
		return lst_len - 1
	h = lst_len - 1
	while l < h:
		mid = (l + h) // 2
		if lst[mid] < target:
			l = mid + 1
		else:
			h = mid
	return l

def Gawen():
	centre_collisions = sorted([i for i in Gawen_ants if Gawen_ants[i] > 1])
	cc_num = len(centre_collisions)
	collisions = cc_num
	if not collisions:
		for (i, j) in ant_steasy:
			collisions += i * j
		return collisions
	for (line_idx, line) in enumerate(lines):
		cc_idx = 0
		for (ant_idx, ant) in enumerate(line):
			if cc_idx < cc_num:
				cc_idx = b_s(centre_collisions, cc_num, cc_idx, abs(ant))
			if abs(ant) == centre_collisions[cc_idx]:
				if ant < 0:
					ant_steasy[line_idx][0] -= 1
					collisions += ant_steasy[line_idx][0]
				else:
					ant_steasy[line_idx][1] -= 1
					collisions += ant_steasy[line_idx][1]
			elif ant < 0:
				ant_steasy[line_idx][0] -= 1
				collisions += ant_steasy[line_idx][1]
			else:
				ant_steasy[line_idx][1] -= 1
				collisions += ant_steasy[line_idx][0]
	return collisions
for _ in range(int(input())):
	N = int(input())
	Gawen_ants = []
	lines = []
	ant_steasy = []
	for i in range(N):
		(M, *ants) = list(map(int, input().split()))
		Gawen_ants.extend(list(map(abs, ants)))
		idx = 0
		negs = b_s_n(ants, M)
		ant_steasy.append([negs, M - negs])
		ants.sort(key=abs)
		lines.append(ants)
	Gawen_ants = Counter(Gawen_ants)
	print(Gawen())