CodeEff/ECCO huggingface dataset:
# Original solution
n = int(eval(input()))
a = list(map(int, input().split()))
b = list(map(int, input().split()))
c = list(map(int, input().split()))
a.sort()
b.sort()
c.sort()
bi = [n for _ in range(n)]
for i in range(n):
    for j in range(n):
        if b[i] <= a[j]:
            bi[i] = j
            break
ans = 0
for i in range(n):
    for j in range(n):
        if c[i] <= b[j]:
            break
        else:
            ans += bi[j]
print(ans)

# Optimized solution
import bisect

n = int(eval(input()))
a = list(map(int, input().split()))
b = list(map(int, input().split()))
c = list(map(int, input().split()))
a.sort()
b.sort()
c.sort()
ans = 0;
for bj in b:
    ai = bisect.bisect_left(a, bj);
    ck = n - bisect.bisect_right(c, bj);
    ans += ai * ck;
print(ans)
# Original solution
from bisect import bisect_left
from collections import defaultdict

N = int(eval(input()))

A = sorted(list(map(int, input().split())))
B = sorted(list(map(int, input().split())))
C = sorted(list(map(int, input().split())))
num_a = 0
num_c = 0
res = 0
pre_b = -1

dict_C = defaultdict(int)

for b in B:
    dict_C[b] = C.count(b)


for b in B:
    if b == pre_b:
        res += num_a * num_c
        continue
    num_a = bisect_left(A, b) # a < b となるAの要素数
    pre_num_c = bisect_left(C, b)
    num_c = N - pre_num_c # c > b となるAの要素数
    if pre_num_c != N and C[pre_num_c] == b:
        num_c -= dict_C[b]
    res += num_a * num_c
    pre_b = b
print(res)



# Optimized solution
from bisect import bisect_left
from collections import defaultdict

N = int(eval(input()))

A = sorted(list(map(int, input().split())))
B = sorted(list(map(int, input().split())))
C = sorted(list(map(int, input().split())))
num_a = 0
num_c = 0
res = 0
pre_b = -1

dict_C = defaultdict(int)


for b in B:
    if b == pre_b:
        res += num_a * num_c
        continue
    num_a = bisect_left(A, b) # a < b となるAの要素数
    pre_num_c = bisect_left(C, b)
    num_c = N - pre_num_c # c > b となるAの要素数
    if pre_num_c != N and C[pre_num_c] == b:
        num_c = N - bisect_left(C, b+1)
    res += num_a * num_c
    pre_b = b
print(res)
# Original solution
from bisect import bisect_left
from collections import defaultdict

N = int(eval(input()))

A = sorted(list(map(int, input().split())))
B = sorted(list(map(int, input().split())))
C = sorted(list(map(int, input().split())))
num_a = 0
num_c = 0
res = 0
pre_b = -1

dict_C = defaultdict(int)


for b in B:
    if b == pre_b:
        res += num_a * num_c
        continue
    num_a = bisect_left(A, b) # a < b となるAの要素数
    pre_num_c = bisect_left(C, b)
    num_c = N - pre_num_c # c > b となるAの要素数
    if pre_num_c != N and C[pre_num_c] == b:
        num_c = N - bisect_left(C, b+1)
    res += num_a * num_c
    pre_b = b
print(res)



# Optimized solution
from bisect import bisect_left
from bisect import bisect_right

N = int(eval(input()))

A = sorted(list(map(int, input().split())))
B = sorted(list(map(int, input().split())))
C = sorted(list(map(int, input().split())))
num_a = 0
num_c = 0
res = 0
pre_b = -1


for b in B:
    if b == pre_b:
        res += num_a * num_c
        continue
    num_a = bisect_left(A, b) # a < b となるAの要素数
    pre_num_c = bisect_right(C, b)
    num_c = N - pre_num_c # c > b となるAの要素数
    res += num_a * num_c
    pre_b = b
print(res)
# Original solution
# abc077_c.py
'''
多分あとは、Bで重複がある場合は探索しないで個数かけていくとかにしないといけない。
'''
def is_okC(idx,key,target):
########## wirte criteria here ##########
    if target[idx] > key:
        return True
    return False

def meguru_bisectC(key,target):
    left = -1
    right = len(target)
    while (abs(right - left) > 1):
        mid = left + (right - left) // 2
        if is_okC(mid,key,target):
            right = mid
        else:
            left = mid
#    print("C : ",target[right:])
    return target[right:]


def is_okA(idx,key,target):
########## wirte criteria here ##########
    if target[idx] >= key:
        return True
    return False

def meguru_bisectA(key,target):
    left = -1
    right = len(target)
    while (abs(right - left) > 1):
        mid = left + (right - left) // 2
#        print("mid : " , mid)
        if is_okA(mid,key,target):
            right = mid
        else:
            left = mid
#    print("A : ",target[:right])
    return target[:right]

N = int(eval(input()))
A = list(map(int,input().split()))
B = list(map(int,input().split()))
C = list(map(int,input().split()))
A.sort()
C.sort()
a = 0
c = 0
ans = 0

for i in B:
    a = len(meguru_bisectA(i,A))
#    print("i : ",i)
    c = len(meguru_bisectC(i,C))
    ans += a*c
#    print()

print(ans)

# Optimized solution
# abc077_c.py
'''
多分あとは、Bで重複がある場合は探索しないで個数かけていくとかにしないといけない。
'''
def is_okC(idx,key,target):
########## wirte criteria here ##########
    if target[idx] > key:
        return True
    return False

def meguru_bisectC(key,target):
    left = -1
    length = len(target)
    right = length
    while (abs(right - left) > 1):
        mid = left + (right - left) // 2
        if is_okC(mid,key,target):
            right = mid
        else:
            left = mid
    return length-right


def is_okA(idx,key,target):
########## wirte criteria here ##########
    if target[idx] >= key:
        return True
    return False

def meguru_bisectA(key,target):
    left = -1
    length = len(target)
    right = length
    while (abs(right - left) > 1):
        mid = left + (right - left) // 2
#        print("mid : " , mid)
        if is_okA(mid,key,target):
            right = mid
        else:
            left = mid
    return right

N = int(eval(input()))
A = list(map(int,input().split()))
B = list(map(int,input().split()))
C = list(map(int,input().split()))
A.sort()
C.sort()
a = 0
c = 0
ans = 0
#print(A)
#print(B)
#print(C)
for i in B:
    a = meguru_bisectA(i,A)
#    print(A[:a] )
#    print("i : ",i)
    c = meguru_bisectC(i,C)
#    print(C[c:])
    ans += a*c
#    print()

print(ans)
# Original solution
def bisect(lst, isok, ok, ng):
    while(abs(ok-ng)>1):
        mid = (ok+ng)//2
        if isok(lst[mid]):
            ok = mid
        else:
            ng = mid
    return [ok, ng]

n = int(eval(input()))
a = [int(i) for i in input().split()]
b = [int(i) for i in input().split()]
c = [int(i) for i in input().split()]

a.sort()
b.sort()
c.sort()

ans = 0

for i in a:
    ind = bisect(b, lambda x:x > i, n, -1)[0]
    if ind == n:
        break
    for j in range(ind, n):
        ans += n - bisect(c, lambda x:x > b[j], n, -1)[0]

print(ans)

# Optimized solution
def bisect(lst, isok, ok, ng):
    while(abs(ok-ng)>1):
        mid = (ok+ng)//2
        if isok(lst[mid]):
            ok = mid
        else:
            ng = mid
    return [ok, ng]

n = int(eval(input()))
a = [int(i) for i in input().split()]
b = [int(i) for i in input().split()]
c = [int(i) for i in input().split()]

a.sort()
b.sort()
c.sort()

ans = 0

for i in b:
    x = bisect(a, lambda x:x < i, -1, n)[0]
    y = bisect(c, lambda x:x > i, n, -1)[0]
    ans += (x+1)*(n-y)

print(ans)
# Original solution
import sys
import itertools
sys.setrecursionlimit(1000000000)
from heapq import heapify,heappop,heappush,heappushpop
import math
import collections
import copy
import bisect

n = int(eval(input()))
A = list(map(int,input().split()))
B = list(map(int,input().split()))
C = list(map(int,input().split()))
A.sort()
B.sort()
C.sort()
ans = 0
for i in range(len(C)):
    b = bisect.bisect_left(B,C[i])
    if b == 0:
        continue
    for j in range(b):
        a = bisect.bisect_left(A,B[j])
        ans += a
print(ans)

# Optimized solution
import sys
import itertools
sys.setrecursionlimit(1000000000)
from heapq import heapify,heappop,heappush,heappushpop
import math
import collections
import copy
import bisect

n = int(eval(input()))
A = list(map(int,input().split()))
B = list(map(int,input().split()))
C = list(map(int,input().split()))
A.sort()
B.sort()
C.sort()
ans = 0
for b in B:
    a = bisect.bisect_left(A,b)
    c = n - bisect.bisect_left(C,b+1)
    ans += a*c
print(ans)
# Original solution
#!/usr/bin/env python3
import sys
from bisect import bisect_right


def solve(N: int, A: "List[int]", B: "List[int]", C: "List[int]"):
    ans  = 0
    A.sort()
    B.sort()
    C.sort()
    for i in range(N):
        bi = bisect_right(B, A[i])
        for j in range(bi, N):
            ci = bisect_right(C, B[j])
            ans += N-ci

    print(ans)

    return


# Generated by 1.1.5 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    A = [int(next(tokens)) for _ in range(N)]  # type: "List[int]"
    B = [int(next(tokens)) for _ in range(N)]  # type: "List[int]"
    C = [int(next(tokens)) for _ in range(N)]  # type: "List[int]"
    solve(N, A, B, C)

if __name__ == '__main__':
    main()


# Optimized solution
#!/usr/bin/env python3
import sys
from bisect import bisect_right, bisect_left


def solve(N: int, A: "List[int]", B: "List[int]", C: "List[int]"):
    ans  = 0
    A.sort()
    B.sort()
    C.sort()
    for i in range(N):
        ai = bisect_left(A, B[i])
        ci = bisect_right(C, B[i])
        ans += (ai) * (N-ci)

    print(ans)

    return


# Generated by 1.1.5 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    A = [int(next(tokens)) for _ in range(N)]  # type: "List[int]"
    B = [int(next(tokens)) for _ in range(N)]  # type: "List[int]"
    C = [int(next(tokens)) for _ in range(N)]  # type: "List[int]"
    solve(N, A, B, C)

if __name__ == '__main__':
    main()
# Original solution
import bisect

N=int(eval(input()))
A=[int(x) for x in input().split()]
B=[int(x) for x in input().split()]
C=[int(x) for x in input().split()]

A.sort()
B.sort()
C.sort()
ans=0
for i in range(N):
  a=bisect.bisect_right(C,B[i])
  b=bisect.bisect_left(A,B[i])
  ans+=(N-a)*b
print(ans)

# Optimized solution
import bisect

N=int(eval(input()))
A=[int(x) for x in input().split()]
B=[int(x) for x in input().split()]
C=[int(x) for x in input().split()]

A.sort()
B.sort()
C.sort()

ans=0

for i in range(N):
  ans+=(bisect.bisect_left(A,B[i])*(N-bisect.bisect_right(C,B[i])))

print(ans)
# Original solution
from collections import Counter
import bisect

N=int(eval(input()))
A=list(map(int,input().split()))
B=list(map(int,input().split()))
C=list(map(int,input().split()))

a_raw=Counter(A)
b_raw=Counter(B)
c_raw=Counter(C)

a=sorted(list(a_raw.items()), key=lambda x: x[0])
c=sorted(list(c_raw.items()), key=lambda x: x[0])

ans=0
for i in b_raw:
    insert_index_a = bisect.bisect_left([a[x][0] for x in range(len(a))],i)
    insert_index_c = bisect.bisect_right([c[y][0] for y in range(len(c))],i)
    if insert_index_a>0 and insert_index_c !=len(c):
        sum_a=sum(a[m][1] for m in range(insert_index_a))
        sum_c=sum(c[n][1] for n in range(insert_index_c,len(c)))
        ans+=sum_a * b_raw[i] * sum_c

print(ans)



# Optimized solution
import bisect

N=int(eval(input()))
A=list(map(int,input().split()))
B=list(map(int,input().split()))
C=list(map(int,input().split()))

A.sort()
B.sort()
C.sort()

ans = 0
for i in B:
    ins_a = bisect.bisect_left(A,i)
    ins_c = bisect.bisect_right(C,i)
    ans+=ins_a*(N-ins_c)

print(ans)
# Original solution
# coding:utf-8

import sys
import math
import time
#import numpy as np
import collections
from collections import deque
from collections import Counter
import queue
import copy
import bisect
import heapq


def dfs(s, prev, pre):
  val[s] += Ope[s] + prev
  for i in G[s]:
    if(i == pre):
      continue
    dfs(i, val[s], s)

def bfs(sx, sy, n):
  que = deque([[sy,sx]])
  while que:
    y,x = que.popleft()
    for i,j in D:
      if(x+i<0 or y+j<0 or x+i>W-1 or y+j>H-1):
        continue
      dist = G[y+j][x+i]
      if(G[y+j][x+i] != "X"):
        if(type(G[y+j][x+i]) is str):
          G[y+j][x+i] = G[y][x]+1
          que.append([y+j,x+i])
        elif(dist>G[y][x]+1):
          G[y+j][x+i] = G[y][x]+1
          que.append([y+j,x+i])
        

def combinations_count(n, r):
  return math.factorial(n) // (math.factorial(n - r) * math.factorial(r))


#sys.setrecursionlimit(10**7)
#N, Q = map(int, input().split())
#G = [list(input()) for i in range(H)]
#INF = V * 10001
#A = [int(i) for i in input().split()]
#AB = [list(map(int, input().split())) for _ in range(K)]



N = int(eval(input()))
A = [int(i) for i in input().split()]
B = [int(i) for i in input().split()]
C = [int(i) for i in input().split()]
ans = 0

A.sort()
B.sort()
C.sort()


for i in range(N):
  temp = bisect.bisect_left(B, A[i]+1)
  for j in range(temp, N):
    ans += (N-bisect.bisect_left(C, B[j]+1))


print(ans)


# Optimized solution
# coding:utf-8

import sys
import math
import time
#import numpy as np
import collections
from collections import deque
from collections import Counter
import queue
import copy
import bisect
import heapq


def dfs(s, prev, pre):
  val[s] += Ope[s] + prev
  for i in G[s]:
    if(i == pre):
      continue
    dfs(i, val[s], s)

def bfs(sx, sy, n):
  que = deque([[sy,sx]])
  while que:
    y,x = que.popleft()
    for i,j in D:
      if(x+i<0 or y+j<0 or x+i>W-1 or y+j>H-1):
        continue
      dist = G[y+j][x+i]
      if(G[y+j][x+i] != "X"):
        if(type(G[y+j][x+i]) is str):
          G[y+j][x+i] = G[y][x]+1
          que.append([y+j,x+i])
        elif(dist>G[y][x]+1):
          G[y+j][x+i] = G[y][x]+1
          que.append([y+j,x+i])
        

def combinations_count(n, r):
  return math.factorial(n) // (math.factorial(n - r) * math.factorial(r))


#sys.setrecursionlimit(10**7)
#N, Q = map(int, input().split())
#G = [list(input()) for i in range(H)]
#INF = V * 10001
#A = [int(i) for i in input().split()]
#AB = [list(map(int, input().split())) for _ in range(K)]



N = int(eval(input()))
A = [int(i) for i in input().split()]
B = [int(i) for i in input().split()]
C = [int(i) for i in input().split()]
AA = [0]*N
BB = [0]*N
ans = 0

A.sort()
B.sort()
C.sort()


for i in range(N):
  AA[i] = bisect.bisect_right(A, B[i]-1)

for j in range(N):
  BB[j] = bisect.bisect_left(C, B[j]+1)

for k in range(N):
  ans += AA[k]*(N-BB[k])

print(ans)
# Original solution
import bisect
N = int(eval(input()))
A = list(map(int,input().split()))
B = list(map(int,input().split()))
C = list(map(int,input().split()))
A.sort()
B.sort()
C.sort()
lb = [0] * len(B)
for i in range(len(B)):
    lb[i]= bisect.bisect_left(A,B[i])

ans = 0    
for i in range(len(C)):
    temp = bisect.bisect_left(B,C[i])
    ans +=sum(lb[0:temp])


print(ans)

# Optimized solution
import bisect
N = int(eval(input()))
A = list(map(int,input().split()))
B = list(map(int,input().split()))
C = list(map(int,input().split()))
A.sort()
B.sort()
C.sort()
lb = [0] * (len(B)+1)
lsum = [0] * (len(B)+1)
temp = 0
for i in range(len(B)):
    lb[i]= bisect.bisect_left(A,B[i])
    
for i in range(len(B)):
    lsum[i] = lb[i] +lsum[i-1]


ans = 0    
for i in range(len(C)):
    temp = bisect.bisect_left(B,C[i])
    ans +=lsum[temp-1]


print(ans)
# Original solution
import bisect

n = int(eval(input()))

a = list(map(int, input().split()))
b = list(map(int, input().split()))
c = list(map(int, input().split()))
a.sort()
b.sort()
c.sort()

b_bt = []
c_bt = []
for i in range(n):
    b_bt.append(bisect.bisect_left(a, b[i]))
    c_bt.append(bisect.bisect_left(b, c[i])-1)
result = 0
for i in range(n):
    if c_bt[i] >= 0:
        result += sum(b_bt[:c_bt[i]+1])
print(result)

# Optimized solution
import bisect

n = int(eval(input()))

a = list(map(int, input().split()))
b = list(map(int, input().split()))
c = list(map(int, input().split()))
a.sort()
b.sort()
c.sort()

result = 0
for i in range(n):
    x = bisect.bisect_left(a, b[i])
    y = n - bisect.bisect_right(c, b[i])
    result += x*y


print(result)
# Original solution
# -*- coding: utf-8 -*-

def get_input() -> tuple:
    """
    標準入力を取得する.

    Returns:\n
        tuple: 標準入力
    """
    N = int(eval(input()))
    A = list(map(int, input().split()))
    B = list(map(int, input().split()))
    C = list(map(int, input().split()))

    return N, A, B, C


def binary_search(l: list, key: int) -> int:
    """
    l[index] > keyとなる最小のindexを求める.

    Args:\n
        l (list): リスト
        key (int): 整数

    Returns:\n
        int: l[index] > keyとなる最小のindex
    """
    low = -1
    high = len(l)
    while 1 < high - low:
        mid = (low + high) // 2
        guess = l[mid]
        if guess > key:
            high = mid
        else:
            low = mid
    return high


def main(N: int, A: list, B: list, C: list) -> None:
    """
    メイン処理.

    Args:\n
        N (int): パーツの数
        A (list): 上部のパーツのサイズ
        B (list): 中部のパーツのサイズ
        C (list): 下部のパーツのサイズ
    """
    # 事前にリストをソートしておく
    A = sorted(A)
    B = sorted(B)
    C = sorted(C)

    # 求解処理
    ans = 0
    for i in range(N):
        A_i = A[i]
        lb_B = binary_search(B, A_i)
        for j in range(lb_B, N):
            B_j = B[j]
            lb_C = binary_search(C, B_j)
            ans += N - lb_C

    # 結果出力
    print(ans)


if __name__ == "__main__":
    # 標準入力を取得
    N, A, B, C = get_input()

    # メイン処理
    main(N, A, B, C)


# Optimized solution
# -*- coding: utf-8 -*-

def get_input() -> tuple:
    """
    標準入力を取得する.

    Returns:\n
        tuple: 標準入力
    """
    N = int(eval(input()))
    A = list(map(int, input().split()))
    B = list(map(int, input().split()))
    C = list(map(int, input().split()))

    return N, A, B, C


def get_lb(l: list, key: int) -> int:
    """
    l[index] > keyとなる最小のindexを求める.

    Args:\n
        l (list): リスト
        key (int): 整数

    Returns:\n
        int: l[index] > keyとなる最小のindex
    """
    low = -1
    high = len(l)
    while 1 < high - low:
        mid = (low + high) // 2
        guess = l[mid]
        if guess > key:
            high = mid
        else:
            low = mid
    return high


def get_ub(l: list, key: int) -> int:
    """
    l[index] < keyとなる最大のindexを求める.

    Args:\n
        l (list): リスト
        key (int): 整数

    Returns:\n
        int: l[index] < keyとなる最大のindex
    """
    low = -1
    high = len(l)
    while 1 < high - low:
        mid = (low + high) // 2
        guess = l[mid]
        if guess < key:
            low = mid
        else:
            high = mid
    return low


def main(N: int, A: list, B: list, C: list) -> None:
    """
    メイン処理.

    Args:\n
        N (int): パーツの数
        A (list): 上部のパーツのサイズ
        B (list): 中部のパーツのサイズ
        C (list): 下部のパーツのサイズ
    """
    # 事前にリストをソートしておく
    A = sorted(A)
    B = sorted(B)
    C = sorted(C)

    # 求解処理
    ans = 0
    for i in range(N):
        B_i = B[i]
        ans += (get_ub(A, B_i) + 1) * (N - get_lb(C, B_i))

    # 結果出力
    print(ans)


if __name__ == "__main__":
    # 標準入力を取得
    N, A, B, C = get_input()

    # メイン処理
    main(N, A, B, C)
# Original solution
# -*- coding: utf-8 -*-
# モジュールのインポート
import itertools

# 標準入力を取得
N = int(eval(input()))
A = list(map(int, input().split()))
B = list(map(int, input().split()))
C = list(map(int, input().split()))

# 求解処理


def get_ub(l: list, x: int) -> int:
    low = -1
    high = len(l)
    while 1 < high - low:
        mid = (high + low) // 2
        guess = l[mid]
        if guess > x:
            high = mid
        else:
            low = mid
    return high


C = sorted(C)
ans = 0
for A_i, B_i in itertools.product(A, B):
    if A_i >= B_i:
        continue
    ans += N - get_ub(C, B_i)

# 結果出力
print(ans)


# Optimized solution
# -*- coding: utf-8 -*-

def get_input() -> tuple:
    """
    標準入力を取得する.

    Returns:\n
        tuple: 標準入力
    """
    N = int(eval(input()))
    A = list(map(int, input().split()))
    B = list(map(int, input().split()))
    C = list(map(int, input().split()))

    return N, A, B, C


def get_lb(l: list, key: int) -> int:
    """
    l[index] > keyとなる最小のindexを求める.

    Args:\n
        l (list): リスト
        key (int): 整数

    Returns:\n
        int: l[index] > keyとなる最小のindex
    """
    low = -1
    high = len(l)
    while 1 < high - low:
        mid = (low + high) // 2
        guess = l[mid]
        if guess > key:
            high = mid
        else:
            low = mid
    return high


def get_ub(l: list, key: int) -> int:
    """
    l[index] < keyとなる最大のindexを求める.

    Args:\n
        l (list): リスト
        key (int): 整数

    Returns:\n
        int: l[index] < keyとなる最大のindex
    """
    low = -1
    high = len(l)
    while 1 < high - low:
        mid = (low + high) // 2
        guess = l[mid]
        if guess < key:
            low = mid
        else:
            high = mid
    return low


def main(N: int, A: list, B: list, C: list) -> None:
    """
    メイン処理.

    Args:\n
        N (int): パーツの数(1 <= N <= 10**5)
        A (list): 上部のパーツのサイズ(1 <= A_i <= 10**9)
        B (list): 中部のパーツのサイズ(1 <= B_i <= 10**9)
        C (list): 下部のパーツのサイズ(1 <= C_i <= 10**9)
    """
    # 事前にリストをソートしておく
    A = sorted(A)
    B = sorted(B)
    C = sorted(C)

    # 求解処理
    ans = 0
    for i in range(N):
        B_i = B[i]
        ans += (get_ub(A, B_i) + 1) * (N - get_lb(C, B_i))

    # 結果出力
    print(ans)


if __name__ == "__main__":
    # 標準入力を取得
    N, A, B, C = get_input()

    # メイン処理
    main(N, A, B, C)
# Original solution
def INT(): return int(eval(input()))
def MAP(): return list(map(int, input().split()))
def LIST(): return list(map(int, input().split()))
import bisect

N = INT()
A = LIST()
B = LIST()
C = LIST()

A.sort()
B.sort()
C.sort()

ans = 0
# for ai in A:
#     i = bisect.bisect_right(B, ai)
#     for bi in B[i:]:
#         j = bisect.bisect_right(C, bi)
#         ans += len(C[j:])

for bi in B:
    i = bisect.bisect_left(A, bi)
    j = bisect.bisect_right(C, bi)
    ans += len(A[:i]) * len(C[j:])


print(ans)

# Optimized solution
def INT(): return int(eval(input()))
def MAP(): return list(map(int, input().split()))
def LIST(): return list(map(int, input().split()))
# import bisect

N = INT()
A = LIST()
B = LIST()
C = LIST()

A.sort()
B.sort()
C.sort()

def binsearch(lst, th, ud="up"):
    left, right = -1, len(lst)
    while right - left > 1:
        mid = (left + right) // 2
        if ud == "up":
            if lst[mid] > th:
                right = mid
            else:
                left = mid
        else:
            if lst[mid] >= th:
                right = mid
            else:
                left = mid
        
    return right if ud == "up" else left


ans = 0
# for ai in A:
#     i = bisect.bisect_right(B, ai)
#     for bi in B[i:]:
#         j = bisect.bisect_right(C, bi)
#         ans += len(C[j:])

for bi in B:
    i = binsearch(A, bi, "down")
    j = binsearch(C, bi, "up")
    ans += (i+1) * (N-j)


print(ans)
# Original solution
import bisect, functools, sys
sys.setrecursionlimit(10**6)
N = int(eval(input()))
A = sorted(int(x) for x in input().split())
B = sorted(int(x) for x in input().split())
C = sorted(int(x) for x in input().split())

@functools.lru_cache(maxsize=None)
def a(n):
    return bisect.bisect_left(A, n)

b_cache = [0] * (N + 1)
b_cached = [False] * (N + 1)
def b_i(i):
    global b_cache, b_cached
    if i >= 1:
        if not b_cached[i - 1]: b_i(i - 1)
        t = b_cache[i - 1] + a(B[i - 1])
        b_cache[i] = t
        b_cached[i] = True
        return t
    return 0

@functools.lru_cache(maxsize=None)
def b(n):
    return b_i(min(N, bisect.bisect_left(B, n)))

def c():
    return sum(b(x) for x in C)

print((c()))

# Optimized solution
N = int(eval(input()))
A = sorted(int(x) for x in input().split())
B = sorted(int(x) for x in input().split())
C = sorted(int(x) for x in input().split())

import bisect
print((sum(bisect.bisect_left(A, b) * (N - bisect.bisect_right(C, b)) for b in B)))