#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 9;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0, 0, -1, 1};
int first[100005], second[100005], have[100005];
bool used[100005], bad[100005];
map<pair<int, int>, int> m;
vector<int> edges[100005], par[100005];
priority_queue<int> mx;
priority_queue<int, vector<int>, greater<int> > mn;
int main() {
  ios_base::sync_with_stdio(0);
  int n;
  while (cin >> n) {
    for (int i = 0; i < n; ++i) {
      cin >> first[i] >> second[i];
      m[make_pair(first[i], second[i])] = i;
    }
    int idx, cur, nxt, cnt;
    for (int i = 0; i < n; ++i) {
      if (!second[i]) continue;
      for (int j = -1; j <= 1; ++j) {
        if (m.count(make_pair(first[i] + j, second[i] - 1))) {
          idx = m[make_pair(first[i] + j, second[i] - 1)];
          edges[i].push_back(idx);
          par[idx].push_back(i);
        }
      }
    }
    bool good;
    memset(bad, 0, sizeof(bad));
    memset(used, 0, sizeof(used));
    memset(have, 0, sizeof(have));
    for (int i = 0; i < n; ++i)
      if (edges[i].size() == 1) bad[edges[i][0]] = 1;
    for (int i = 0; i < n; ++i) {
      if (!bad[i]) {
        mx.push(i);
        mn.push(i);
      }
      have[i] = edges[i].size();
    }
    long long int res = 0;
    for (int i = 0; i < n; ++i) {
      if (i & 1) {
        while (mn.size() && (used[mn.top()] || bad[mn.top()])) mn.pop();
        assert(mn.size());
        idx = mn.top();
        mn.pop();
      } else {
        while (mx.size() && (used[mx.top()] || bad[mx.top()])) mx.pop();
        assert(mx.size());
        idx = mx.top();
        mx.pop();
      }
      used[idx] = 1;
      res *= n;
      res = (res + idx) % mod;
      if (have[idx] == 1) {
        for (int j = 0; j < edges[idx].size(); ++j) {
          nxt = edges[idx][j];
          if (!used[nxt] && bad[nxt]) {
            good = 1;
            for (int k = 0; k < par[nxt].size(); ++k) {
              cur = par[nxt][k];
              if (cur == idx || used[cur]) continue;
              if (have[cur] > 1) continue;
              good = 0;
            }
            if (good) {
              bad[nxt] = 0;
              mx.push(nxt);
              mn.push(nxt);
            }
          }
        }
      }
      for (int j = 0; j < par[idx].size(); ++j) {
        cur = par[idx][j];
        if (used[cur]) continue;
        have[cur]--;
        assert(have[cur] >= 1);
        if (have[cur] == 1) {
          cnt = 0;
          for (int k = 0; k < edges[cur].size(); ++k) {
            nxt = edges[cur][k];
            if (!used[nxt] && !bad[nxt]) {
              bad[nxt] = 1;
              ++cnt;
            }
          }
          assert(cnt <= 1);
        }
      }
    }
    cout << res << "\n";
    for (int i = 0; i < n; ++i) {
      edges[i].clear();
      par[i].clear();
    }
    while (mx.size()) mx.pop();
    while (mn.size()) mn.pop();
    m.clear();
  }
  return 0;
}
