Submission #1135341

#TimeUsernameProblemLanguageResultExecution timeMemory
1135341duckindogJoker (BOI20_joker)C++17
100 / 100
953 ms24676 KiB
#include <bits/stdc++.h>

using namespace std;

struct LCT { 
  struct Node { 
    int l, r, p;
    bool flip;
    int valueMin, mi;
    int valueSum, sum;
    Node() : l(0), r(0), p(0), flip(false), valueMin(0), mi(0), 
              valueSum(0), sum(0) {}
  };

  vector<Node> a;
  LCT(int size) : a(size + 1) {}

  bool side(int u) const { 
    return a[a[u].p].r == u;
  }
  bool isRoot(int u) const { 
    return !a[u].p || (a[a[u].p].l != u && a[a[u].p].r != u);
  }
  void push(int u) { 
    if (a[u].flip) { 
      a[u].flip = false;
      swap(a[u].l, a[u].r);
      if (a[u].l) a[a[u].l].flip ^= 1;
      if (a[u].r) a[a[u].r].flip ^= 1;
    }
  }
  void pull(int u) { 
    a[u].sum = a[u].valueSum + a[a[u].l].sum + a[a[u].r].sum;

    int lt = a[a[u].l].mi, rt = a[a[u].r].mi;
    a[u].mi = u;
    if (a[a[u].mi].valueMin > a[lt].valueMin) a[u].mi = lt;
    if (a[a[u].mi].valueMin > a[rt].valueMin) a[u].mi = rt;
  }
  void attach(int u, int dir, int child) { 
    if (child) a[child].p = u;
    (dir ? a[u].r : a[u].l) = child;
    pull(u);
  }

  // SPLAY TREE OPERATOR
  void rotate(int u) {
    const int p = a[u].p, parP = a[p].p;
    push(p); push(u);
    
    if (!isRoot(p)) attach(parP, side(p), u);
    a[u].p = parP;
    
    const int dir = (a[p].r == u);
    attach(p, dir, dir ? a[u].l : a[u].r);
    attach(u, !dir, p);

    pull(parP);
  }
  void splay(int u) { 
    for (; !isRoot(u); rotate(u)) { 
      if (!isRoot(a[u].p))
        rotate(side(a[u].p) == side(u) ? a[u].p : u);
    }
    push(u);
  }
  // END TAG

  // BASE OPERATOR
  int access(int u) { 
    int last = 0;
    for (int p = u; p; p = a[p].p) {
      splay(p);
      a[p].r = last;
      pull(last = p);
    }
    splay(u);
    return last;
  }
  void makeRoot(int u) {
    access(u);
    if (a[u].l)
      a[a[u].l].flip = true, a[u].l = 0;
    pull(u);
  }
  // END TAG

  // QUERY OPERATOR
  int lca(int u, int v) { 
    if (u == v) return u;
    access(u);
    int ret = access(v);
    return a[u].p ? ret : 0;
  }
  bool isConnected(int u, int v) { 
    return lca(u, v); }

  int queryMin(int u, int v) { 
    makeRoot(u); 
    access(v);
    return a[v].mi;
  }
  int querySum(int u, int v) { 
    makeRoot(u); 
    access(v);
    return a[v].sum;
  }
  // END TAG

  // MODIFICATION
  void link(int u, int v) { 
    makeRoot(v);
    a[v].p = u;
  }
  void cut(int u) { 
    access(u);
    a[a[u].l].p = 0, a[u].l = 0;
    pull(u);
  }
  void cut(int u, int v) { 
    makeRoot(u);
    access(v);
    cut(v);
  }
  // END TAG
};

int32_t main() { 
  cin.tie()->sync_with_stdio(0);

  int n, m, q; cin >> n >> m >> q;
  
  vector<pair<int, int>> edge(m + 1);
  for (int i = 1; i <= m; ++i) cin >> edge[i].first >> edge[i].second;
  for (int i = 1; i <= m; ++i) 
    edge[i].first += 2 * m, edge[i].second += 2 * m;
  edge.insert(edge.end(), edge.begin() + 1, edge.end());

  LCT T(n + 2 * m);
  for (int i = 1; i <= 2 * m; ++i) 
    T.a[i].valueSum = 1, T.a[i].valueMin = i;
  T.a[0].valueMin = 1'000'000;
  for (int i = 2 * m + 1; i <= 2 * m + n; ++i)
    T.a[i].valueMin = 1'000'000;

  auto chk = [&](int idx) { 
    const auto& [u, v] = edge[idx];
    if (!T.isConnected(u, v)) return true;
    return T.querySum(u, v) % 2 != 0;
  };
  
  vector<bool> mk(2 * m + 1);
  auto cut = [&](int idx) { 
    assert(idx <= 2 * m);
    const auto& [u, v] = edge[idx];
    
    mk[idx] = false;
    T.cut(u, idx);
    T.cut(idx, v);
  };
  auto link = [&](int idx) { 
    const auto& [u, v] = edge[idx];
    if (T.isConnected(u, v)) cut(T.queryMin(u, v));
    
    mk[idx] = true;
    T.link(u, idx);
    T.link(idx, v);
  };

  vector<int> rightMost(2 * m + 1);
  for (int l = 1, r = 1; l <= 2 * m; ++l) { 
    while (r <= 2 * m && chk(r)) link(r++);
    rightMost[l] = r - 1;
    if (mk[l]) cut(l);
  }
  
  while (q--) { 
    int l, r; cin >> l >> r;
    cout << (rightMost[r + 1] < m + l - 1 ? "YES" : "NO") << "\n";
  }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...