#include <bits/stdc++.h>
using namespace std;
const int MAX_INT = std::numeric_limits<int>::max();
const int MIN_INT = std::numeric_limits<int>::min();
const int INF = 1000000000;
const int NEG_INF = -1000000000;
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
int lcm(int a, int b) { return a * (b / gcd(a, b)); }
long long MOD = 1000 * 1000 * 1000 + 9;
int M;
vector<pair<long long, long long> > cube_idx;
map<pair<long long, long long>, int> cubes;
map<long long, pair<long long, long long> > Idx1, Idx2;
bool isStable(long long x, long long y, pair<long long, long long> c) {
  if (y == 0 || !cubes.count(pair<long long, long long>(x, y))) return true;
  for (int i = -1; i <= 1; ++i) {
    if (c.first == x + i) continue;
    if (cubes.count(pair<long long, long long>(x + i, y - 1))) return true;
  }
  return false;
}
bool cantake(pair<long long, long long> c) {
  long long x = c.first, y = c.second;
  return isStable(x - 1, y + 1, c) && isStable(x, y + 1, c) &&
         isStable(x + 1, y + 1, c);
}
bool cantake(int i) {
  pair<long long, long long> c = cube_idx[i];
  return cantake(c);
}
void take(int i) {
  pair<long long, long long> c = cube_idx[i];
  long long x = c.first, y = c.second;
  map<pair<long long, long long>, int>::iterator it = cubes.find(c);
  cubes.erase(it);
}
long long modMult(long long a, long long b) {
  return ((a % MOD) * (b % MOD)) % MOD;
}
long long modPow(long long b, long long e) {
  if (e <= 0) return 1ll;
  long long ans = modPow(b, e / 2);
  ans = modMult(ans, ans);
  if (e & 1) ans = modMult(ans, b);
  return ans;
}
long long toMbase(const vector<long long> &n, int B) {
  long long ans = 0;
  int l = n.size();
  for (int i = 0; i < n.size(); ++i)
    ans = (ans % MOD) + (modMult(n[i], modPow(B, l - i - 1)) % MOD);
  return ans;
}
inline void solve() {
  cin >> M;
  vector<long long> taken(M, 0), number;
  for (int i = 0; i < M; ++i) {
    long long x, y;
    cin >> x >> y;
    pair<long long, long long> c(x, y);
    cube_idx.push_back(c);
    cubes[c] = i;
  }
  for (int i = 0; i < M; ++i) {
    if (cantake(i)) {
      Idx1[-i] = cube_idx[i];
      Idx2[i] = cube_idx[i];
    }
  }
  int turn = 1;
  while (!cubes.empty()) {
    map<long long, pair<long long, long long> >::iterator p1 = Idx1.begin(),
                                                          p2 = Idx2.begin();
    int nxt_cube_idx;
    pair<long long, long long> nxt_cube;
    if (turn & 1) {
      nxt_cube_idx = p1->first;
      nxt_cube = p1->second;
    } else {
      nxt_cube_idx = p2->first;
      nxt_cube = p2->second;
    }
    nxt_cube_idx = abs(nxt_cube_idx);
    number.push_back(nxt_cube_idx);
    Idx1.erase(-nxt_cube_idx);
    Idx2.erase(nxt_cube_idx);
    cubes.erase(nxt_cube);
    long long x = nxt_cube.first, y = nxt_cube.second;
    for (int i = -2; i <= 2; ++i) {
      if (cubes.find(pair<long long, long long>(x + i, y)) == cubes.end())
        continue;
      int rem = cubes[pair<long long, long long>(x + i, y)];
      if (Idx2.find(rem) == Idx2.end()) continue;
      if (cantake(pair<long long, long long>(x + i, y))) continue;
      Idx1.erase(-rem);
      Idx2.erase(rem);
    }
    for (int i = -1; i <= 1; ++i) {
      map<pair<long long, long long>, int>::iterator cube1 =
          cubes.find(pair<long long, long long>(x + i, y - 1));
      if (cube1 != cubes.end())
        if (cantake(cube1->first)) {
          int i = cube1->second;
          Idx1[-i] = cube1->first;
          Idx2[i] = cube1->first;
        }
    }
    turn++;
  }
  long long res = toMbase(number, M);
  cout << res << endl;
}
int main() {
  solve();
  return 0;
}
