#include <bits/stdc++.h>
using namespace std;
struct Data {
  int64_t value;
  int64_t supports;
  int64_t supportedBy;
};
bool isTop(map<pair<int64_t, int64_t>, Data> const& cubes,
           pair<int64_t, int64_t> const& pos) {
  bool top = true;
  for (int64_t i = -1; i <= 1; ++i) {
    map<pair<int64_t, int64_t>, Data>::const_iterator f =
        cubes.find(pair<int64_t, int64_t>{pos.first + i, pos.second + 1});
    if (f != cubes.end()) {
      if (f->second.supportedBy <= 1) {
        top = false;
        break;
      }
    }
  }
  return top;
}
int main(int, char**) {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  int64_t n;
  cin >> n;
  map<pair<int64_t, int64_t>, Data> cubes;
  for (int64_t i = 0; i < n; ++i) {
    int64_t x, y;
    cin >> x >> y;
    cubes.insert(make_pair(pair<int64_t, int64_t>{x, y}, Data{i, 0, 0}));
  }
  for (auto& p : cubes) {
    Data& data = p.second;
    pair<int64_t, int64_t> const& pos = p.first;
    if (cubes.find(pair<int64_t, int64_t>{pos.first - 1, pos.second - 1}) !=
        cubes.end())
      data.supportedBy += 1;
    if (cubes.find(pair<int64_t, int64_t>{pos.first, pos.second - 1}) !=
        cubes.end())
      data.supportedBy += 1;
    if (cubes.find(pair<int64_t, int64_t>{pos.first + 1, pos.second - 1}) !=
        cubes.end())
      data.supportedBy += 1;
    if (cubes.find(pair<int64_t, int64_t>{pos.first - 1, pos.second + 1}) !=
        cubes.end())
      data.supports += 1;
    if (cubes.find(pair<int64_t, int64_t>{pos.first, pos.second + 1}) !=
        cubes.end())
      data.supports += 1;
    if (cubes.find(pair<int64_t, int64_t>{pos.first + 1, pos.second + 1}) !=
        cubes.end())
      data.supports += 1;
  }
  set<pair<int64_t, pair<int64_t, int64_t> > > tops;
  for (auto const& p : cubes) {
    int64_t value = p.second.value;
    pair<int64_t, int64_t> const& pos = p.first;
    if (isTop(cubes, pos))
      tops.insert(pair<int64_t, pair<int64_t, int64_t> >{value, pos});
  }
  int64_t result = 0;
  bool smallest = false;
  while (!tops.empty()) {
    set<pair<int64_t, pair<int64_t, int64_t> > >::iterator used;
    if (smallest)
      used = tops.begin();
    else
      used = --tops.end();
    smallest = !smallest;
    result *= n;
    result += used->first;
    result %= 1000000009l;
    pair<int64_t, int64_t> pos = used->second;
    cubes.erase(pos);
    tops.erase(used);
    set<pair<int64_t, pair<int64_t, int64_t> > > update;
    for (int64_t i = -1; i <= 1; ++i) {
      {
        pair<int64_t, int64_t> pm1{pos.first + i, pos.second - 1};
        map<pair<int64_t, int64_t>, Data>::iterator fm1 = cubes.find(pm1);
        if (fm1 != cubes.end()) {
          fm1->second.supports -= 1;
          update.insert(
              pair<int64_t, pair<int64_t, int64_t> >{fm1->second.value, pm1});
        }
      }
      {
        pair<int64_t, int64_t> pp1{pos.first + i, pos.second + 1};
        map<pair<int64_t, int64_t>, Data>::iterator fp1 = cubes.find(pp1);
        if (fp1 != cubes.end()) {
          fp1->second.supportedBy -= 1;
          update.insert(
              pair<int64_t, pair<int64_t, int64_t> >{fp1->second.value, pp1});
          if (fp1->second.supportedBy <= 1) {
            for (int64_t j = -1; j <= 1; ++j) {
              pair<int64_t, int64_t> sibP{pp1.first + j, pos.second};
              map<pair<int64_t, int64_t>, Data>::iterator sibI =
                  cubes.find(sibP);
              if (sibI != cubes.end()) {
                tops.erase(pair<int64_t, pair<int64_t, int64_t> >{
                    sibI->second.value, sibP});
              }
            }
          }
        }
      }
    }
    for (auto const& updatePos : update) {
      if (isTop(cubes, updatePos.second)) tops.insert(updatePos);
    }
  }
  cout << result << endl;
  return 0;
}
