#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 10;
template <typename A, typename B>
ostream& operator<<(ostream& out, pair<A, B> p) {
  out << "{ " << p.first << ", " << p.second << " }";
  return out;
}
template <typename T>
ostream& operator<<(ostream& out, vector<T> v) {
  out << "[ ";
  for (int i = 0; i < int((v).size()); i++) {
    out << v[i];
    if (i != int((v).size()) - 1) out << " ,";
  }
  out << " ]";
  return out;
}
struct DSU {
  pair<int, int> par[maxn];
  vector<pair<int, pair<int, int> > > vec;
  vector<int> rec;
  DSU() {
    for (int i = 0; i < maxn; i++) par[i].first = -1;
  }
  void record() { rec.push_back(int((vec).size())); }
  void undo() {
    assert(int((rec).size()));
    int SZ = rec.back();
    for (rec.pop_back(); int((vec).size()) > SZ; vec.pop_back())
      par[vec.back().first] = vec.back().second;
  }
  pair<int, int> fnd(int u) {
    if (par[u].first < 0) return {u, 0};
    pair<int, int> p = fnd(par[u].first);
    p.second ^= par[u].second;
    return p;
  }
  bool mrg(int a, int b) {
    pair<int, int> A = fnd(a), B = fnd(b);
    if (A.first == B.first) return A.second != B.second;
    if (par[A.first] > par[B.first]) swap(A, B);
    vec.push_back({A.first, par[A.first]});
    vec.push_back({B.first, par[B.first]});
    par[A.first].first += par[B.first].first;
    par[B.first].first = A.first;
    par[B.first].second = A.second ^ B.second ^ 1;
    return 1;
  }
};
DSU dsu[55];
vector<int> edges[maxn];
vector<int> qur[4 * maxn];
int A[maxn], B[maxn], ID[maxn], C[maxn], NC[maxn];
bool ans[maxn];
int q;
void add(int f, int s, int l = 0, int r = q, int id = 1) {
  if (f >= s || l >= r || s <= l || r <= f) return;
  if (f <= l && r <= s) {
    qur[id].push_back(f - 1);
    return;
  }
  int mid = (l + r) >> 1;
  add(f, s, l, mid, 2 * id);
  add(f, s, mid, r, 2 * id + 1);
}
void solve(int l = 0, int r = q, int id = 1) {
  for (int i = 0; i < 55; i++) dsu[i].record();
  for (auto p : qur[id]) {
    if (C[p] == 0) continue;
    bool x = dsu[C[p]].mrg(A[ID[p]], B[ID[p]]);
    assert(x);
  }
  if (r - l == 1) {
    assert(C[l]);
    if (dsu[C[l]].mrg(A[ID[l]], B[ID[l]])) {
      ans[l] = 0;
    } else {
      C[l] = NC[ID[l]];
      ans[l] = 1;
    }
    NC[ID[l]] = C[l];
  } else {
    int mid = (l + r) >> 1;
    solve(l, mid, 2 * id);
    solve(mid, r, 2 * id + 1);
  }
  for (int i = 0; i < 55; i++) dsu[i].undo();
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie();
  int n, m, k;
  cin >> n >> m >> k >> q;
  for (int i = 0; i < m; i++) {
    cin >> A[i] >> B[i];
  }
  for (int i = 0; i < q; i++) {
    cin >> ID[i] >> C[i];
    edges[--ID[i]].push_back(i);
  }
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < int((edges[i]).size()); j++)
      add(edges[i][j] + 1,
          j == int((edges[i]).size()) - 1 ? q : edges[i][j + 1]);
  }
  solve();
  for (int i = 0; i < q; i++) {
    cout << (ans[i] ? "NO\n" : "YES\n");
  }
  return 0;
}
