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
using splay_key = int;
struct splay_node {
  splay_node *parent = nullptr, *child[2] = {nullptr, nullptr};
  splay_key key;
  int size = 1;
  static int get_size(splay_node *x) { return x == nullptr ? 0 : x->size; }
  int parent_index() const {
    if (parent == nullptr) return -1;
    return this == parent->child[0] ? 0 : 1;
  }
  void set_child(int index, splay_node *x) {
    child[index] = x;
    if (x != nullptr) x->parent = this;
  }
  void join() { size = get_size(child[0]) + get_size(child[1]) + 1; }
};
auto random_address = [] {
  char *p = new char;
  delete p;
  return uint64_t(p);
};
mt19937_64 splay_rng(chrono::steady_clock::now().time_since_epoch().count() *
                     (random_address() | 1));
int64_t splay_count = 0;
struct splay_tree {
  static const int POOL_SIZE = 10000;
  static vector<splay_node *> node_pool;
  static vector<splay_node *> pointers_to_delete;
  static splay_node *new_node(const splay_key &key) {
    if (node_pool.empty()) {
      splay_node *ptr = new splay_node[POOL_SIZE];
      pointers_to_delete.push_back(ptr);
      for (int i = POOL_SIZE - 1; i >= 0; i--) node_pool.push_back(ptr + i);
    }
    splay_node *node = node_pool.back();
    node_pool.pop_back();
    node->key = key;
    return node;
  }
  static void _delete_pointers() {
    static bool deleted = false;
    if (!deleted) {
      for (splay_node *node : pointers_to_delete) delete[] node;
      deleted = true;
    }
  }
  splay_node *root = nullptr;
  splay_tree() { atexit(_delete_pointers); }
  bool empty() const { return root == nullptr; }
  int size() const { return root == nullptr ? 0 : root->size; }
  splay_node *set_root(splay_node *x) {
    if (x != nullptr) x->parent = nullptr;
    return root = x;
  }
  void rotate_up(splay_node *x, bool x_join = true) {
    splay_node *p = x->parent, *gp = p->parent;
    int index = x->parent_index();
    if (gp == nullptr)
      set_root(x);
    else
      gp->set_child(p->parent_index(), x);
    p->set_child(index, x->child[!index]);
    x->set_child(!index, p);
    p->join();
    if (x_join) x->join();
  }
  void splay(splay_node *x) {
    splay_count++;
    while (x != root) {
      splay_node *p = x->parent;
      if (p != root)
        rotate_up(x->parent_index() == p->parent_index() ? p : x, false);
      rotate_up(x, false);
    }
    x->join();
  }
  static constexpr double SPLAY_RNG_RANGE = double(splay_rng.max()) + 1.0;
  static constexpr double LOG_CONSTANT = 2.0;
  static constexpr double SPLAY_PROBABILITY = 0.25;
  static const int SIZE_CUTOFF = 100;
  void check_splay(splay_node *x, int depth) {
    int n = size(), log_n = 32 - __builtin_clz(n);
    if (depth > LOG_CONSTANT * log_n ||
        (n < SIZE_CUTOFF &&
         double(splay_rng()) < SPLAY_PROBABILITY * SPLAY_RNG_RANGE))
      splay(x);
  }
  pair<splay_node *, int> insert(const splay_key &key,
                                 bool require_unique = false) {
    return insert(new_node(key), require_unique);
  }
  pair<splay_node *, int> insert(splay_node *x, bool require_unique = false) {
    if (root == nullptr) return {set_root(x), 0};
    splay_node *current = root, *prev = nullptr;
    int below = 0, depth = 0;
    while (current != nullptr) {
      prev = current;
      depth++;
      if (current->key < x->key) {
        below += splay_node::get_size(current->child[0]) + 1;
        current = current->child[1];
      } else {
        if (require_unique && !(x->key < current->key)) {
          below += splay_node::get_size(current->child[0]);
          check_splay(current, depth);
          return {current, below};
        }
        current = current->child[0];
      }
    }
    prev->set_child(prev->key < x->key ? 1 : 0, x);
    check_splay(x, depth);
    for (splay_node *node = x; node != nullptr; node = node->parent)
      node->join();
    return {x, below};
  }
  splay_node *begin() {
    if (root == nullptr) return nullptr;
    splay_node *x = root;
    int depth = 0;
    while (x->child[0] != nullptr) {
      x = x->child[0];
      depth++;
    }
    check_splay(x, depth);
    return x;
  }
  splay_node *successor(splay_node *x) const {
    if (x == nullptr) return nullptr;
    if (x->child[1] != nullptr) {
      x = x->child[1];
      while (x->child[0] != nullptr) x = x->child[0];
      return x;
    }
    while (x->parent_index() == 1) x = x->parent;
    return x->parent;
  }
  splay_node *predecessor(splay_node *x) const {
    if (x == nullptr) return nullptr;
    if (x->child[0] != nullptr) {
      x = x->child[0];
      while (x->child[1] != nullptr) x = x->child[1];
      return x;
    }
    while (x->parent_index() == 0) x = x->parent;
    return x->parent;
  }
  splay_node *last() {
    if (root == nullptr) return nullptr;
    splay_node *x = root;
    int depth = 0;
    while (x->child[1] != nullptr) {
      x = x->child[1];
      depth++;
    }
    check_splay(x, depth);
    return x;
  }
  void clear() {
    vector<splay_node *> nodes;
    nodes.reserve(size());
    for (splay_node *node = begin(); node != nullptr; node = successor(node))
      nodes.push_back(node);
    for (splay_node *node : nodes) {
      *node = splay_node();
      node_pool.push_back(node);
    }
    set_root(nullptr);
  }
  void erase(splay_node *x) {
    splay_node *new_x = nullptr, *fix_node = nullptr;
    if (x->child[0] == nullptr || x->child[1] == nullptr) {
      new_x = x->child[x->child[0] == nullptr ? 1 : 0];
      fix_node = x->parent;
    } else {
      splay_node *next = successor(x);
      assert(next != nullptr && next->child[0] == nullptr);
      new_x = next;
      fix_node = next->parent == x ? next : next->parent;
      next->parent->set_child(next->parent_index(), next->child[1]);
      next->set_child(0, x->child[0]);
      next->set_child(1, x->child[1]);
    }
    if (x == root)
      set_root(new_x);
    else
      x->parent->set_child(x->parent_index(), new_x);
    int depth = 0;
    for (splay_node *node = fix_node; node != nullptr; node = node->parent) {
      node->join();
      depth++;
    }
    if (fix_node != nullptr) check_splay(fix_node, depth);
    *x = splay_node();
    node_pool.push_back(x);
  }
  pair<splay_node *, int> lower_bound(const splay_key &key) {
    splay_node *current = root, *prev = nullptr, *answer = nullptr;
    int below = 0, depth = 0;
    while (current != nullptr) {
      prev = current;
      depth++;
      if (current->key < key) {
        below += splay_node::get_size(current->child[0]) + 1;
        current = current->child[1];
      } else {
        answer = current;
        current = current->child[0];
      }
    }
    if (prev != nullptr) check_splay(prev, depth);
    return make_pair(answer, below);
  }
  bool contains(const splay_key &key) {
    splay_node *node = lower_bound(key).first;
    return node != nullptr && node->key == key;
  }
  bool erase(const splay_key &key) {
    splay_node *x = lower_bound(key).first;
    if (x == nullptr || x->key != key) return false;
    erase(x);
    return true;
  }
  splay_node *node_at_index(int index) {
    if (index < 0 || index >= size()) return nullptr;
    splay_node *current = root;
    int depth = 0;
    while (current != nullptr) {
      int left_size = splay_node::get_size(current->child[0]);
      depth++;
      if (index == left_size) {
        check_splay(current, depth);
        return current;
      }
      if (index < left_size) {
        current = current->child[0];
      } else {
        current = current->child[1];
        index -= left_size + 1;
      }
    }
    assert(false);
  }
  splay_node *query_prefix_key(const splay_key &key) {
    splay_node *node = lower_bound(key).first;
    if (node == nullptr) return root;
    splay(node);
    return node->child[0];
  }
  splay_node *query_prefix_count(int prefix) {
    if (prefix <= 0) return nullptr;
    if (prefix >= size()) return root;
    splay_node *node = node_at_index(prefix);
    splay(node);
    return node->child[0];
  }
  splay_node *query_suffix_key(const splay_key &key) {
    splay_node *node = lower_bound(key).first;
    if (node == nullptr) return nullptr;
    node = predecessor(node);
    if (node == nullptr) return root;
    splay(node);
    return node->child[1];
  }
  splay_node *query_suffix_count(int suffix) {
    if (suffix <= 0) return root;
    if (suffix >= size()) return nullptr;
    splay_node *node = node_at_index(suffix - 1);
    splay(node);
    return node->child[1];
  }
};
vector<splay_node *> splay_tree::node_pool;
vector<splay_node *> splay_tree::pointers_to_delete;
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(splay_tree &s) { return s.size() == 0 ? INF : s.begin()->key; }
int get_max(splay_tree &s) { return s.size() == 0 ? -INF : s.last()->key; }
int main() {
  IO::init();
  int N, M, Q;
  IO::read_int(N, M, Q);
  basic_seg_tree tree(N);
  vector<splay_tree> 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].contains(c))
      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');
  }
}