Problem: Note that the difference between easy and hard versions is that in hard version unavailable cells can become available again and in easy version can't. You can make hacks only if all versions are solved.

Ildar and Ivan are tired of chess, but they really like the chessboard, so they invented a new game. The field is a chessboard 2n × 2m: it has 2n rows, 2m columns, and the cell in row i and column j is colored white if i+j is even, and is colored black otherwise.

The game proceeds as follows: Ildar marks some of the white cells of the chessboard as unavailable, and asks Ivan to place n × m kings on the remaining white cells in such way, so that there are no kings attacking each other. A king can attack another king if they are located in the adjacent cells, sharing an edge or a corner.

Ildar would like to explore different combinations of cells. Initially all cells are marked as available, and then he has q queries. In each query he marks a cell as unavailable. After each query he would like to know whether it is possible to place the kings on the available cells in a desired way. Please help him!

Input

The first line of input contains three integers n, m, q (1 ≤ n, m, q ≤ 200 000) — the size of the board and the number of queries.

q lines follow, each of them contains a description of a query: two integers i and j, denoting a white cell (i, j) on the board (1 ≤ i ≤ 2n, 1 ≤ j ≤ 2m, i + j is even) that becomes unavailable. It's guaranteed, that each cell (i, j) appears in input at most once.

Output

Output q lines, i-th line should contain answer for a board after i queries of Ildar. This line should contain "YES" if it is possible to place the kings on the available cells in the desired way, or "NO" otherwise.

Examples

Input


1 3 3
1 1
1 5
2 4


Output


YES
YES
NO


Input


3 2 7
4 2
6 4
1 3
2 2
2 4
4 4
3 1


Output


YES
YES
NO
NO
NO
NO
NO

Note

In the first example case after the second query only cells (1, 1) and (1, 5) are unavailable. Then Ivan can place three kings on cells (2, 2), (2, 4) and (2, 6).

After the third query three cells (1, 1), (1, 5) and (2, 4) are unavailable, so there remain only 3 available cells: (2, 2), (1, 3) and (2, 6). Ivan can not put 3 kings on those cells, because kings on cells (2, 2) and (1, 3) attack each other, since these cells share a corner.

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  os << '{';
  string sep;
  for (const auto &x : v) os << sep << x, sep = ", ";
  return os << '}';
}
template <typename T, size_t size>
ostream &operator<<(ostream &os, const array<T, size> &arr) {
  os << '{';
  string sep;
  for (const auto &x : arr) os << sep << x, sep = ", ";
  return os << '}';
}
template <typename A, typename B>
ostream &operator<<(ostream &os, const pair<A, B> &p) {
  return os << '(' << p.first << ", " << p.second << ')';
}
void dbg_out() { cerr << endl; }
template <typename Head, typename... Tail>
void dbg_out(Head H, Tail... T) {
  cerr << ' ' << H;
  dbg_out(T...);
}
namespace IO {
const int BUFFER_SIZE = 1 << 15;
char input_buffer[BUFFER_SIZE];
size_t input_pos = 0, input_len = 0;
char output_buffer[BUFFER_SIZE];
int output_pos = 0;
char number_buffer[100];
uint8_t lookup[100];
void _update_input_buffer() {
  input_len = fread(input_buffer, sizeof(char), BUFFER_SIZE, stdin);
  input_pos = 0;
  if (input_len == 0) input_buffer[0] = EOF;
}
inline char next_char(bool advance = true) {
  if (input_pos >= input_len) _update_input_buffer();
  return input_buffer[advance ? input_pos++ : input_pos];
}
inline bool isspace(char c) {
  return (unsigned char)(c - '\t') < 5 || c == ' ';
}
inline void read_char(char &c) {
  while (isspace(next_char(false))) next_char();
  c = next_char();
}
template <typename T>
inline void read_int(T &number) {
  bool negative = false;
  number = 0;
  while (!isdigit(next_char(false)))
    if (next_char() == '-') negative = true;
  do {
    number = 10 * number + (next_char() - '0');
  } while (isdigit(next_char(false)));
  if (negative) number = -number;
}
template <typename T, typename... Args>
inline void read_int(T &number, Args &...args) {
  read_int(number);
  read_int(args...);
}
inline void read_str(string &str) {
  while (isspace(next_char(false))) next_char();
  str.clear();
  do {
    str += next_char();
  } while (!isspace(next_char(false)));
}
void _flush_output() {
  fwrite(output_buffer, sizeof(char), output_pos, stdout);
  output_pos = 0;
}
inline void write_char(char c) {
  if (output_pos == BUFFER_SIZE) _flush_output();
  output_buffer[output_pos++] = c;
}
template <typename T>
inline void write_int(T number, char after = '\0') {
  if (number < 0) {
    write_char('-');
    number = -number;
  }
  int length = 0;
  while (number >= 10) {
    uint8_t lookup_value = lookup[number % 100];
    number /= 100;
    number_buffer[length++] = char((lookup_value & 15) + '0');
    number_buffer[length++] = char((lookup_value >> 4) + '0');
  }
  if (number != 0 || length == 0) write_char(char(number + '0'));
  for (int i = length - 1; i >= 0; i--) write_char(number_buffer[i]);
  if (after) write_char(after);
}
inline void write_str(const string &str, char after = '\0') {
  for (char c : str) write_char(c);
  if (after) write_char(after);
}
void init() {
  bool exit_success = atexit(_flush_output) == 0;
  assert(exit_success);
  for (int i = 0; i < 100; i++) lookup[i] = uint8_t((i / 10 << 4) + i % 10);
}
}  // namespace IO
struct segment_change {
  static const int SENTINEL = numeric_limits<int>::lowest();
  int set_min, set_max;
  segment_change(int _set_min = SENTINEL, int _set_max = SENTINEL)
      : set_min(_set_min), set_max(_set_max) {}
};
struct segment {
  int minimum, maximum;
  bool bad;
  segment(int _minimum = numeric_limits<int>::max(),
          int _maximum = numeric_limits<int>::lowest()) {
    minimum = _minimum;
    maximum = _maximum;
    bad = minimum <= maximum;
  }
  void apply(const segment_change &change) {
    if (change.set_min != segment_change::SENTINEL) minimum = change.set_min;
    if (change.set_max != segment_change::SENTINEL) maximum = change.set_max;
    bad = minimum <= maximum;
  }
  void join(const segment &other) {
    bad = bad || other.bad || minimum <= other.maximum;
    minimum = min(minimum, other.minimum);
    maximum = max(maximum, other.maximum);
  }
  void join(const segment &a, const segment &b) {
    *this = a;
    join(b);
  }
};
int right_half[32];
struct basic_seg_tree {
  static const bool POWER_OF_TWO_MODE = true;
  int tree_n = 0;
  vector<segment> tree;
  basic_seg_tree(int n = -1) {
    if (n >= 0) init(n);
  }
  void init(int n) {
    if (POWER_OF_TWO_MODE) {
      tree_n = 1;
      while (tree_n < n) tree_n *= 2;
    } else {
      tree_n = n;
    }
    tree.assign(2 * tree_n, segment());
  }
  void build(const vector<segment> &initial) {
    int n = int(initial.size());
    init(n);
    assert(n <= tree_n);
    for (int i = 0; i < n; i++) tree[tree_n + i] = initial[i];
    for (int position = tree_n - 1; position > 0; position--)
      tree[position].join(tree[2 * position], tree[2 * position + 1]);
  }
  segment query(int a, int b) const {
    assert(0 <= a && a <= b && b <= tree_n);
    segment answer;
    int r_size = 0;
    for (a += tree_n, b += tree_n; a < b; a /= 2, b /= 2) {
      if (a & 1) answer.join(tree[a++]);
      if (b & 1) right_half[r_size++] = --b;
    }
    for (int i = r_size - 1; i >= 0; i--) answer.join(tree[right_half[i]]);
    return answer;
  }
  segment query_single(int index) const {
    assert(0 <= index && index < tree_n);
    return tree[tree_n + index];
  }
  void join_up(int position) {
    while (position > 1) {
      position /= 2;
      tree[position].join(tree[2 * position], tree[2 * position + 1]);
    }
  }
  void update(int index, const segment_change &change) {
    assert(0 <= index && index < tree_n);
    int position = tree_n + index;
    tree[position].apply(change);
    join_up(position);
  }
  void update(int index, const segment &seg) {
    assert(0 <= index && index < tree_n);
    int position = tree_n + index;
    tree[position] = seg;
    join_up(position);
  }
};
const int INF = 1e9 + 5;
int get_min(const set<int> &s) { return s.empty() ? INF : *s.begin(); }
int get_max(const set<int> &s) { return s.empty() ? -INF : *s.rbegin(); }
int main() {
  IO::init();
  int N, M, Q;
  IO::read_int(N, M, Q);
  basic_seg_tree tree(N);
  vector<set<int>> columns[2];
  columns[0].resize(N);
  columns[1].resize(N);
  for (int q = 0; q < Q; q++) {
    int r, c;
    IO::read_int(r, c);
    r--;
    c--;
    int type = r % 2;
    r /= 2;
    c /= 2;
    if (columns[type][r].find(c) == columns[type][r].end())
      columns[type][r].insert(c);
    else
      columns[type][r].erase(c);
    if (type == 0)
      tree.update(r, segment_change(get_min(columns[type][r]),
                                    segment_change::SENTINEL));
    else
      tree.update(r, segment_change(segment_change::SENTINEL,
                                    get_max(columns[type][r])));
    IO::write_str(tree.tree[1].bad ? "NO" : "YES", '\n');
  }
}