Problem:
Score : 300 points

Problem Statement

The season for Snuke Festival has come again this year. First of all, Ringo will perform a ritual to summon Snuke. For the ritual, he needs an altar, which consists of three parts, one in each of the three categories: upper, middle and lower.

He has N parts for each of the three categories. The size of the i-th upper part is A_i, the size of the i-th middle part is B_i, and the size of the i-th lower part is C_i.

To build an altar, the size of the middle part must be strictly greater than that of the upper part, and the size of the lower part must be strictly greater than that of the middle part. On the other hand, any three parts that satisfy these conditions can be combined to form an altar.

How many different altars can Ringo build? Here, two altars are considered different when at least one of the three parts used is different.

Constraints

1 \leq N \leq 10^5

1 \leq A_i \leq 10^9(1\leq i\leq N)

1 \leq B_i \leq 10^9(1\leq i\leq N)

1 \leq C_i \leq 10^9(1\leq i\leq N)

All input values are integers.

Input

Input is given from Standard Input in the following format:

N
A_1 ... A_N
B_1 ... B_N
C_1 ... C_N

Output

Print the number of different altars that Ringo can build.

Sample Input 1

2
1 5
2 4
3 6

Sample Output 1

3

The following three altars can be built:

Upper: 1-st part, Middle: 1-st part, Lower: 1-st part

Upper: 1-st part, Middle: 1-st part, Lower: 2-nd part

Upper: 1-st part, Middle: 2-nd part, Lower: 2-nd part

Sample Input 2

3
1 1 1
2 2 2
3 3 3

Sample Output 2

27

Sample Input 3

6
3 14 159 2 6 53
58 9 79 323 84 6
2643 383 2 79 50 288

Sample Output 3

87

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static System.Math;
using static Math2;
using static Output;
using static Utils;

public class CP
{

  public void Solve()
  {
    Input sc = new Input();
    var n = sc.cin<int>();
    var a = sc.cinarr<int>();
    var b = sc.cinarr<int>();
    var c = sc.cinarr<int>();
    Array.Sort(a);
    Array.Sort(c);
    long ans = 0;
    for (int i = 0; i < n; ++i)
    {
      long ue = BinarySearch.Lower_Bound(a, b[i]);
      long sita = n - BinarySearch.Upper_Bound(c, b[i]);
      ans += ue * sita;
    }
    Put(ans);
  }
}
public class BinarySearch
{
  public static int Lower_Bound<T>(IList<T> Array, T Target)
  {
    return Lower_Bound<T>(Array, Target, Comparer<T>.Default.Compare);
  }
  public static int Lower_Bound<T>(IList<T> Array, T Target, Comparison<T> Comp)
  {
    var cmp = Comparer<T>.Create(Comp);
    var l = -1; //always ng
    var r = Array.Count(); //always ok
    while (r - l > 1)
    {
      var mid = l + (r - l) / 2;
      var res = cmp.Compare(Array[mid], Target);
      if (res >= 0) r = mid;
      else l = mid;
    }
    return r;
  }
  public static int Upper_Bound<T>(IList<T> Array, T Target)
  {
    return Upper_Bound<T>(Array, Target, Comparer<T>.Default.Compare);
  }
  public static int Upper_Bound<T>(IList<T> Array, T Target, Comparison<T> Comp)
  {
    var cmp = Comparer<T>.Create(Comp);
    var l = -1;
    var r = Array.Count;
    while (r - l > 1)
    {
      var mid = l + (r - l) / 2;
      var res = cmp.Compare(Array[mid], Target);
      if (res > 0) r = mid;
      else l = mid;
    }
    return r;
  }
}
public static class Math2
{
  public const int INF = 1 << 29;
  public const long INFL = 1L << 60;
  public const long MOD = 1000000007;
  public const long MOD2 = 998244353;

  public static long Power(long a, long b, long MOD = 1000000007) //i^N
  {
    long res = 1;
    while (b > 0)
    {
      if ((b & 1) != 0) res = res * a % MOD;
      a = a * a % MOD;
      b >>= 1;
    }
    return res;
  }
  public static long Power2(long a, long b) //i^N
  {
    long res = 1;
    while (b > 0)
    {
      if ((b & 1) != 0) res = res * a;
      a = a * a;
      b >>= 1;
    }
    return res;
  }
  public static long GCD(long a, long b)
  {
    if (a == 0) return b;
    while (b > 0)
    {
      var r = a % b;
      a = b;
      b = r;
    }
    return a;
  }
  public static long LCM(long a, long b) => (b / GCD(a, b)) * a;
  public static long Comb(long n, long r, int MOD = 1000000007)
  {
    if (r > n - r) r = n - r;
    long Nume = 1;
    long Deno = 1;

    if (r > n - r) r = n - r;
    for (long i = 1; i <= r; ++i)
    {
      Deno = (Deno * i) % MOD;
      Nume = Nume * (n - i + 1) % MOD;
    }
    return (Nume * inv(Deno)) % MOD;
  }
  public static long Comb2(long n, long r)
  {
    long Nume = 1;
    long Deno = 1;

    if (r > n - r) r = n - r;
    for (long i = 1; i <= r; ++i)
    {
      Deno *= i;
      Nume *= n - i + 1;
    }
    return Nume / Deno;
  }
  public static long inv(long x, int MOD = 1000000007)
  {
    return Power(x, MOD - 2, MOD);
  }
}
public static class Utils
{
  public static void Swap<T>(ref T A, ref T B)
  {
    T x = A;
    A = B;
    B = x;
  }
  public static int DigitSum(string N)
  {

    int ret = 0;
    for (int i = 0; i < N.Length; ++i) ret += N[i] - '0';
    return ret;
  }
  public static string ConvertBase(long N, int K)
  {
    StringBuilder ret = new StringBuilder();
    while (N > 0)
    {
      var r = N % K;
      N /= K;
      ret.Append(r);
    }
    return new string(ret.ToString().ToCharArray().Reverse().ToArray());
  }
  public static bool NextPermutation<T>(IList<T> lis, Comparison<T> cmp)
  {
    int n = lis.Count;
    int i = n - 1;
    while (i - 1 >= 0)
    {
      if (cmp(lis[i - 1], lis[i]) < 0) break;
      --i;
    }
    if (i == 0) return false;
    int j = i;
    while (j + 1 < n)
    {
      if (cmp(lis[i - 1], lis[j + 1]) > 0) break;
      ++j;
    }
    var _q = lis[j];
    lis[j] = lis[i - 1];
    lis[i - 1] = _q;
    int k = i;
    int l = n - 1;
    while (k < l)
    {
      var _p = lis[k];
      lis[k] = lis[l];
      lis[l] = _p;

      ++k;
      --l;
    }
    return true;
  }
  public static bool NextPermutation<T>(IList<T> lis) => NextPermutation(lis, Comparer<T>.Default.Compare);
}
public class PriorityQueue<T>
{
  List<T> _item;
  public int Count { get { return _item.Count; } }
  bool _isascend { get; set; }
  public T Peek { get { return _item[0]; } }
  Comparison<T> Comp;
  public PriorityQueue(bool IsAscend = true, IEnumerable<T> list = null) : this(Comparer<T>.Default.Compare, IsAscend, list) { }
  public PriorityQueue(Comparison<T> cmp, bool IsAscend = true, IEnumerable<T> list = null)
  {
    _item = new List<T>();
    _isascend = IsAscend;
    this.Comp = cmp;
    if (list != null)
    {
      _item.AddRange(list);
      Build();
    }
  }

  private int Compare(int i, int j) => (_isascend ? -1 : 1) * Comp(_item[i], _item[j]);
  private void Swap(int i, int j) { var t = _item[i]; _item[i] = _item[j]; _item[j] = t; }
  private int Parent(int i) => (i - 1) >> 1;
  private int Left(int i) => (i << 1) + 1;
  public T Enqueue(T val)
  {
    int i = _item.Count;
    _item.Add(val);
    while (i > 0)
    {
      int p = Parent(i);
      if (Compare(i, p) > 0)
        Swap(i, p);
      i = p;
    }
    return val;
  }
  private void Heapify(int index)
  {
    for (int i = index, j;
      (j = Left(i)) < _item.Count; i = j)
    {
      if (j != _item.Count - 1 && Compare(j, j + 1) < 0) j++;
      if (Compare(i, j) < 0)
        Swap(i, j);
    }
  }
  public T Dequeue()
  {
    T val = _item[0];
    _item[0] = _item[_item.Count - 1];
    _item.RemoveAt(_item.Count - 1);
    Heapify(0);
    return val;
  }
  private void Build()
  {
    for (var i = (_item.Count >> 1) - 1; i >= 0; i--)
      Heapify(i);
  }
  public bool Any() => Count > 0;
}
class Program
{
  static void Main(string[] args)
  {
    var CP = new CP();
    CP.Solve();
  }
}
public static class Output
{

  public static void Put(string a) => Console.WriteLine(a);
  public static void Put(params object[] i) => Put(string.Join(" ", i));
  public static void Put<T>(IEnumerable<T> a) => Put(string.Join(" ", a));
  public static void PutV<T>(IEnumerable<T> a) { foreach (var z in a) Put(z); }
  public static void YN(bool i)
  {
    if (i) Put("Yes");
    else Put("No");
  }
}
public class Input
{
  public static string Str => Console.ReadLine();
  public static bool IsTypeEqual<T, U>() => typeof(T).Equals(typeof(U));
  public static T ConvertType<T, U>(U a) => (T)Convert.ChangeType(a, typeof(T));
  public static T Cast<T>(string s)
  {
    if (IsTypeEqual<T, int>()) return ConvertType<T, int>(int.Parse(s));
    else if (IsTypeEqual<T, long>()) return ConvertType<T, long>(long.Parse(s));
    else if (IsTypeEqual<T, double>()) return ConvertType<T, double>(double.Parse(s));
    else if (IsTypeEqual<T, char>()) return ConvertType<T, char>(char.Parse(s));
    else return ConvertType<T, string>(s);
  }
  public static T[] Castarr<T>(string[] s)
  {

    var ret = new T[s.Length];
    int i = 0;
    if (IsTypeEqual<T, char>())
    {
      var list = new List<T>();
      foreach (var t in s)
      {
        foreach (var u in t)
        {
          list.Add(ConvertType<T, char>(char.Parse(u.ToString())));
        }
      }
      return list.ToArray();
    }
    foreach (var t in s)
    {
      if (IsTypeEqual<T, int>()) ret[i++] = ConvertType<T, int>(int.Parse(t));
      else if (IsTypeEqual<T, long>()) ret[i++] = ConvertType<T, long>(long.Parse(t));
      else if (IsTypeEqual<T, double>()) ret[i++] = ConvertType<T, double>(double.Parse(t));
      else ret[i++] = ConvertType<T, string>(t);
    }
    return ret;
  }
  Queue<string> q = new Queue<string>();
  void next() { var ss = Str.Split(' '); foreach (var item in ss) q.Enqueue(item); }
  public T cin<T>() { if (!q.Any()) next(); return Cast<T>(q.Dequeue()); }
  public void mul<T>(out T t) { t = cin<T>(); }
  public void mul<T, U>(out T t, out U u) { t = cin<T>(); u = cin<U>(); }
  public void mul<T, U, V>(out T t, out U u, out V v) { t = cin<T>(); u = cin<U>(); v = cin<V>(); }
  public void mul<T, U, V, W>(out T t, out U u, out V v, out W w) { t = cin<T>(); u = cin<U>(); v = cin<V>(); w = cin<W>(); }
  public void mul<T, U, V, W, X>(out T t, out U u, out V v, out W w, out X x) { t = cin<T>(); u = cin<U>(); v = cin<V>(); w = cin<W>(); x = cin<X>(); }
  public void mul<T, U, V, W, X, Y>(out T t, out U u, out V v, out W w, out X x, out Y y) { t = cin<T>(); u = cin<U>(); v = cin<V>(); w = cin<W>(); x = cin<X>(); y = cin<Y>(); }
  public void mul<T, U, V, W, X, Y, Z>(out T t, out U u, out V v, out W w, out X x, out Y y, out Z z) { t = cin<T>(); u = cin<U>(); v = cin<V>(); w = cin<W>(); x = cin<X>(); y = cin<Y>(); z = cin<Z>(); }
  public T[] cinarr<T>() { return Castarr<T>(Str.Split(' ')); }
}