You are given an undirected graph consisting of n vertices. Initially there are no edges in the graph. Also you are given q queries, each query either adds one undirected edge to the graph or removes it. After each query you have to check if the resulting graph is bipartite (that is, you can paint all vertices of the graph into two colors so that there is no edge connecting two vertices of the same color).

Input

The first line contains two integers n and q (2 ≤ n, q ≤ 100000).

Then q lines follow. ith line contains two numbers xi and yi (1 ≤ xi < yi ≤ n). These numbers describe ith query: if there is an edge between vertices xi and yi, then remove it, otherwise add it.

Output

Print q lines. ith line must contain YES if the graph is bipartite after ith query, and NO otherwise.

Example

Input

3 5
2 3
1 3
1 2
1 2
1 2


Output

YES
YES
NO
YES
NO
#include <bits/stdc++.h>
using namespace std;
constexpr int N = 2e5 + 42;
constexpr int BATCH_SIZE = 400;
struct edge_t {
  int i, j;
};
bool operator<(const edge_t &lhs, const edge_t &rhs) {
  if (lhs.i == rhs.i) return lhs.j < rhs.j;
  return lhs.i < rhs.i;
}
int n;
vector<edge_t> batch;
vector<bool> answers;
unordered_set<int> g[N];
int pole_id[2 * N];
int color[2 * N];
bool us[2 * N];
unordered_multiset<int> gc[2 * N];
set<edge_t> edges_to_add;
bool used_vertices[N];
bool has_edge(edge_t ed) {
  return g[ed.i].count(ed.j) > 0 && g[ed.j].count(ed.i) > 0;
}
void modify_edge(edge_t e) {
  if (has_edge(e)) {
    g[e.i].erase(e.j);
    g[e.j].erase(e.i);
  } else {
    g[e.i].insert(e.j);
    g[e.j].insert(e.i);
  }
}
void process_batch() {
  edges_to_add.clear();
  fill(begin(used_vertices), end(used_vertices), false);
  int cnt = 0;
  for (const auto &e : batch) {
    if (has_edge(e)) {
      modify_edge(e);
      edges_to_add.insert(e);
    }
    if (!used_vertices[e.i]) cnt++;
    if (!used_vertices[e.j]) cnt++;
    used_vertices[e.i] = true;
    used_vertices[e.j] = true;
  }
  int pole_count = 0;
  fill(begin(us), begin(us) + n, false);
  for (int i = 0; i < n; i++) {
    gc[i].clear();
  }
  bool bad_base_graph = false;
  for (int i = 0; i < n; i++) {
    if (us[i]) continue;
    vector<int> vs;
    queue<int> q;
    bool has_used_vertices = false;
    q.push(i);
    us[i] = true;
    color[i] = 0;
    while (!q.empty()) {
      int v = q.front();
      q.pop();
      vs.push_back(v);
      if (used_vertices[v] > 0) {
        has_used_vertices = true;
      }
      for (int u : g[v]) {
        if (us[u]) continue;
        us[u] = true;
        q.push(u);
        color[u] = color[v] ^ 1;
      }
    }
    int pole0, pole1;
    if (has_used_vertices) {
      pole0 = pole_count++;
      if (vs.size() > 1) {
        pole1 = pole_count++;
      }
      for (int v : vs) {
        pole_id[v] = (color[v] == 0) ? pole0 : pole1;
      }
    }
    bool added = false;
    for (int v : vs) {
      for (int u : g[v]) {
        if (color[v] == color[u]) {
          bad_base_graph = true;
        } else if (has_used_vertices && !added) {
          added = true;
          gc[pole0].insert(pole1);
          gc[pole1].insert(pole0);
        }
      }
    }
  }
  queue<int> qc;
  for (const auto &e : edges_to_add) {
    edge_t e_c{.i = pole_id[e.i], .j = pole_id[e.j]};
    gc[e_c.i].insert(e_c.j);
    gc[e_c.j].insert(e_c.i);
  }
  for (const auto &e : batch) {
    edge_t e_c{.i = pole_id[e.i], .j = pole_id[e.j]};
    if (edges_to_add.count(e) > 0) {
      edges_to_add.erase(e);
      gc[e_c.i].erase(e_c.j);
      gc[e_c.j].erase(e_c.i);
    } else {
      edges_to_add.insert(e);
      gc[e_c.i].insert(e_c.j);
      gc[e_c.j].insert(e_c.i);
    }
    bool good_g = !bad_base_graph;
    fill(begin(us), begin(us) + pole_count, false);
    fill(begin(color), begin(color) + pole_count, false);
    for (int r = 0; r < pole_count; r++) {
      if (us[r]) continue;
      while (!qc.empty()) qc.pop();
      qc.push(r);
      us[r] = true;
      color[r] = 0;
      while (!qc.empty()) {
        int vc = qc.front();
        qc.pop();
        for (int uc : gc[vc]) {
          if (us[uc]) continue;
          qc.push(uc);
          us[uc] = true;
          color[uc] = color[vc] ^ 1;
        }
        for (int uc : gc[vc]) {
          if (color[vc] == color[uc]) {
            good_g = false;
          }
          if (!good_g) break;
        }
        if (!good_g) break;
      }
      if (!good_g) break;
    }
    answers.push_back(good_g);
  }
  batch.clear();
  for (const auto &add_e : edges_to_add) {
    modify_edge(add_e);
  }
}
int main() {
  ios::sync_with_stdio(false);
  int q;
  cin >> n >> q;
  while (q-- > 0) {
    int u, v;
    cin >> u >> v;
    u--;
    v--;
    batch.push_back(edge_t{.i = u, .j = v});
    if (batch.size() >= BATCH_SIZE) process_batch();
  }
  if (batch.size()) {
    process_batch();
  }
  for (auto answer : answers) {
    cout << (answer ? "YES" : "NO") << "\n";
  }
  return 0;
}
