#include <bits/stdc++.h>
using namespace std;
template <class T, size_t D>
struct vec : vector<vec<T, D - 1>> {
  template <class... Args>
  vec(size_t n = 0, Args... args)
      : vector<vec<T, D - 1>>(n, vec<T, D - 1>(args...)) {}
};
template <class T>
struct vec<T, 1> : vector<T> {
  template <class... Args>
  vec(Args... args) : vector<T>(args...) {}
};
template <class T>
inline bool Minimize(T& a, const T& b) {
  return a > b ? a = b, true : false;
}
template <class T>
inline bool Maximize(T& a, const T& b) {
  return a < b ? a = b, true : false;
}
inline int Next(int i, int n) { return i == n - 1 ? 0 : i + 1; }
inline int Prev(int i, int n) { return !i ? n - 1 : i - 1; }
mt19937 rng(static_cast<uint32_t>(
    chrono::steady_clock::now().time_since_epoch().count()));
struct DSU {
  int n_sets;
  vec<int, 1> parents, cardinalities;
  DSU(int t_n_sets)
      : n_sets(t_n_sets), parents(n_sets), cardinalities(n_sets, 1) {
    iota((parents).begin(), (parents).end(), 0);
  }
  int Parent(int i) {
    return i == parents[i] ? i : parents[i] = Parent(parents[i]);
  }
  bool SameSet(int i, int j) { return Parent(i) == Parent(j); }
  bool Unite(int i, int j) {
    i = Parent(i);
    j = Parent(j);
    if (i == j) {
      return false;
    }
    if (cardinalities[i] > cardinalities[j]) {
      swap(i, j);
    }
    --n_sets;
    parents[i] = j;
    cardinalities[j] += cardinalities[i];
    return true;
  }
};
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int n_rows, n_columns, n;
  cin >> n_rows >> n_columns >> n;
  auto Index = [&](int i, int j) { return i * (n_columns << 1) + j; };
  int answer = 0;
  vec<bool, 2> reclamated(n_rows, n_columns << 1);
  DSU dsu(n_rows * (n_columns << 1));
  vec<int, 1> new_indices(n_rows * (n_columns << 1));
  while (n--) {
    int x, y;
    cin >> x >> y;
    --x;
    --y;
    vec<int, 1> vertices;
    vec<pair<int, int>, 1> edges;
    reclamated[x][y] = true;
    for (int i = -1; i <= 1; ++i) {
      for (int j = -1; j <= 1; ++j) {
        int next_x = x + i, next_y = y + j;
        if (next_y < 0) {
          next_y += n_columns << 1;
        } else if (next_y >= (n_columns << 1)) {
          next_y -= n_columns << 1;
        }
        if (next_x < 0 || next_x >= n_rows || !reclamated[next_x][next_y]) {
          continue;
        }
        vertices.emplace_back(dsu.Parent(Index(next_x, next_y)));
        edges.emplace_back(dsu.Parent(Index(x, y)),
                           dsu.Parent(Index(next_x, next_y)));
      }
    }
    reclamated[x][y + n_columns] = true;
    for (int i = -1; i <= 1; ++i) {
      for (int j = -1; j <= 1; ++j) {
        int next_x = x + i, next_y = y + n_columns + j;
        if (next_y < 0) {
          next_y += n_columns << 1;
        } else if (next_y >= (n_columns << 1)) {
          next_y -= n_columns << 1;
        }
        if (next_x < 0 || next_x >= n_rows || !reclamated[next_x][next_y]) {
          continue;
        }
        vertices.emplace_back(dsu.Parent(Index(next_x, next_y)));
        edges.emplace_back(dsu.Parent(Index(x, y + n_columns)),
                           dsu.Parent(Index(next_x, next_y)));
      }
    }
    sort((vertices).begin(), (vertices).end());
    vertices.erase(unique((vertices).begin(), (vertices).end()),
                   vertices.end());
    for (int i = 0; i < static_cast<int>((vertices).size()); ++i) {
      new_indices[vertices[i]] = i;
    }
    DSU dsu_2(static_cast<int>((vertices).size()));
    for (auto& edge : edges) {
      dsu_2.Unite(new_indices[edge.first], new_indices[edge.second]);
    }
    if (!dsu_2.SameSet(new_indices[dsu.Parent(Index(x, y))],
                       new_indices[dsu.Parent(Index(x, y + n_columns))])) {
      ++answer;
      for (auto& edge : edges) {
        dsu.Unite(edge.first, edge.second);
      }
    } else {
      reclamated[x][y] = reclamated[x][y + n_columns] = false;
    }
  }
  cout << answer << '\n';
  return 0;
}
