#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <functional>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
using namespace std;
using llong = long long;

//===
template<class Monoid, class OP = function<Monoid(const Monoid, const Monoid)> >
struct DynamicSegmentTree {
    struct Node {
        Node *left, *right;
        Monoid v;
        Node(Monoid v):v(v), left(nullptr), right(nullptr) {}
    };

    using llong = long long;

    Node *root = nullptr;
    llong L = 0, R = 0;
    const OP merge_monoid; // bin'operation
    const Monoid e;

    DynamicSegmentTree(const Monoid &e, const OP &f):
        e(e), merge_monoid(f) {};

    inline void eval(Node &u) {
        Monoid lv = e, rv = e;
        if (u.left) lv = u.left->v;
        if (u.right) rv = u.right->v;
        u.v = merge_monoid(lv, rv);
    };

    inline void expand(llong i) {
        if (L == R) {
            R++;
            while (i >= R) R += R - L;
            while (i < L) L -= R - L;
            root = new Node(e);
        }
        else {
            Node *tmp;
            while (i >= R) {
                R += R - L;
                tmp = new Node(root->v);
                tmp->left = root;
                root = tmp;
            }
            while (i < L) {
                L -= R - L;
                tmp = new Node(root->v);
                tmp->right = root;
                root = tmp;
            }
        }
    };

    inline void update(llong i, Monoid v) {
        if (i < L || R <= i) expand(i);
        update(root, L, R, i, v);
    };

    void update(Node *node, llong nl, llong nr, llong k, Monoid v) {
        if (nr - nl <= 1) {
            node->v = v;
            return;
        }

        llong mid = (nl + nr) / 2;
        if (k < mid) {
            if (!node->left) node->left = new Node(e);
            update(node->left, nl, (nl + nr) / 2, k, v);
        }
        else {
            if (!node->right) node->right = new Node(e);
            update(node->right, (nl + nr) / 2, nr, k, v);
        }

        eval(*node);
        return;
    }

    // [l, r)
    inline Monoid fold(llong l, llong r) {
        if (l < L) expand(l);
        if (r > R) expand(r);
        return fold(root, L, R, l, r);
    };
    Monoid fold(Node *node, llong nl, llong nr, llong ql, llong qr) {
        if (ql <= nl && nr <= qr) return node->v;

        Monoid lv = e, rv = e;
        llong mid = (nl + nr) / 2;
        if (node->left && ql < mid && nl < qr) {
            lv = fold(node->left, nl, mid, ql, qr);
        }
        if (node->right && ql < nr && mid < qr) {
            rv = fold(node->right, mid, nr, ql, qr);
        }

        return merge_monoid(lv, rv);
    };
    
    Monoid operator[] (const llong k) {
        return fold(k, k + 1);
    };
};
//===

llong n;
llong a[100005];
llong b[100005];
llong c[100005];
auto f = [](llong l, llong r){return l + r;};
DynamicSegmentTree<llong, decltype(f)> set_a(0, f);
DynamicSegmentTree<llong, decltype(f)> set_c(0, f);

int main() {
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        set_a.update(a[i], set_a[a[i]] + 1);
    }
    for (int i = 0; i < n; i++) {
        cin >> b[i];
    }
    for (int i = 0; i < n; i++) {
        cin >> c[i];
        set_c.update(c[i], set_c[c[i]] + 1);
    }

    llong ans = 0;
    for (int i = 0; i < n; i++) {
        ans += set_a.fold(0, b[i]) * set_c.fold(b[i] + 1, 100000000000ll);
    }

    cout << ans << endl;

    return 0;
}


Measured memory_bytes: 92416