#include <bits/stdc++.h>
using namespace std;
const long long SIZE = 4e5 + 5;
long long n, tn;
long long tree[SIZE], l[SIZE], r[SIZE];
struct node {
  long long x, y, idx;
} a[SIZE];
namespace ae86 {
const long long bufl = 1 << 15;
char buf[bufl], *s = buf, *t = buf;
inline long long fetch() {
  if (s == t) {
    t = (s = buf) + fread(buf, 1, bufl, stdin);
    if (s == t) return EOF;
  }
  return *s++;
}
inline long long read() {
  long long a = 0, b = 1, c = fetch();
  while (!isdigit(c)) b ^= c == '-', c = fetch();
  while (isdigit(c)) a = a * 10 + c - 48, c = fetch();
  return b ? a : -a;
}
}  // namespace ae86
using ae86::read;
long long query(long long pos) {
  long long ans = 0;
  for (; pos; pos -= (pos & (-pos))) ans += tree[pos];
  return ans;
}
void modify(long long pos, long long val) {
  for (; pos <= tn; pos += (pos & (-pos))) tree[pos] += val;
}
long long cmp1(node a, node b) { return a.x == b.x ? a.y < b.y : a.x < b.x; }
long long cmp2(node a, node b) { return a.y == b.y ? a.x > b.x : a.y > b.y; }
signed main() {
  n = read(), tn = n << 1;
  for (long long i = 1; i <= n; ++i) {
    a[i].x = read(), a[i].y = read(), a[i].idx = i;
    if (a[i].x > a[i].y) std::swap(a[i].x, a[i].y);
  }
  std::sort(a + 1, a + n + 1, cmp1);
  for (long long i = 1; i <= n; ++i) {
    l[a[i].idx] += query(a[i].x) + query(tn) - query(a[i].y);
    modify(a[i].y, 1);
  }
  memset(tree, 0, sizeof(tree));
  for (long long i = n; i; --i) {
    r[a[i].idx] += query(a[i].y) - query(a[i].x);
    modify(a[i].y, 1);
  }
  std::sort(a + 1, a + n + 1, cmp2);
  memset(tree, 0, sizeof(tree));
  for (long long i = 1; i <= n; ++i) {
    l[a[i].idx] += query(tn) - query(a[i].y);
    modify(a[i].x, 1);
  }
  long long tot = n * (n - 1) * (n - 2) / 6, ans1 = 0, ans2 = 0;
  for (long long i = 1; i <= n; ++i) {
    ans1 += l[i] * r[i], ans2 += (l[i] + r[i]) * (n - l[i] - r[i] - 1);
  }
  printf("%lld\n", tot - ans1 - (ans2 / 2));
  return 0;
}
