#include <bits/stdc++.h>
using namespace std;
const int maxn = 100050;
struct UnionSet {
  int s[maxn];
  UnionSet(int n) {
    for (int i = 0; i <= n; i++) {
      s[i] = i;
    }
  }
  int gets(int x) {
    if (s[x] == x)
      return x;
    else
      return s[x] = gets(s[x]);
  }
  void merge(int x, int y) {
    int fx = s[gets(x)];
    int fy = s[gets(y)];
    if (fx != fy) s[fx] = fy;
  }
};
template <class T>
inline bool Read(T &ret) {
  char c;
  int sgn;
  if (c = getchar(), c == EOF) return 0;
  while (c != '-' && (c < '0' || c > '9')) c = getchar();
  sgn = (c == '-') ? -1 : 1;
  ret = (c == '-') ? 0 : (c - '0');
  while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
  ret *= sgn;
  return 1;
}
void Out(int a) {
  if (a < 0) {
    putchar('-');
    a = -a;
  }
  if (a >= 10) Out(a / 10);
  putchar(a % 10 + '0');
}
queue<int> que[maxn];
int maxTopoInSet[maxn];
UnionSet us(0);
int topo[maxn];
vector<int> e[maxn];
int rudu[maxn];
queue<int> topoQue;
vector<int> lcae[maxn];
int fat[maxn];
int f[maxn][20];
int dep[maxn];
int siz[maxn];
int Lev;
int n, m, k, q;
void dfs(int v) {
  int en = lcae[v].size();
  for (int i = 0; i < en; i++) {
    int etm = lcae[v][i];
    if (etm != fat[v]) {
      fat[etm] = v;
      dep[etm] = dep[v] + 1;
      dfs(etm);
      siz[v] += siz[etm];
    }
  }
  siz[v]++;
}
int lca(int x, int y) {
  if (dep[x] < dep[y]) swap(x, y);
  if (dep[x] != dep[y]) {
    int i;
    for (i = 0; dep[f[x][i]] >= dep[y]; i++)
      ;
    i--;
    x = f[x][i];
    while (dep[x] > dep[y]) x = fat[x];
  }
  if (x == y) return y;
  for (int i = Lev; i >= 0; i--)
    if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
  return f[x][0];
}
int tpn[maxn];
int main() {
  scanf("%d%d%d%d", &n, &m, &k, &q);
  us = UnionSet(n);
  for (int i = 0; i < k; i++) {
    int a, b;
    Read(a);
    Read(b);
    if (que[b].empty())
      ;
    else {
      int ber = que[b].back();
      e[ber].push_back(a);
      lcae[ber].push_back(a);
      lcae[a].push_back(ber);
      rudu[a]++;
      us.merge(a, ber);
    }
    que[b].push(a);
  }
  for (int i = 1; i <= n; i++) {
    if (rudu[i] == 0) {
      int si = us.gets(i);
      tpn[si] = 1;
      topo[i] = tpn[si]++;
      topoQue.push(i);
      dep[i] = 1;
      dfs(i);
    }
  }
  while (!topoQue.empty()) {
    int x = topoQue.front();
    topoQue.pop();
    for (auto to : e[x]) {
      rudu[to]--;
      if (rudu[to] == 0) {
        int sto = us.gets(to);
        topo[to] = tpn[sto]++;
        topoQue.push(to);
      }
    }
  }
  for (int i = 1; i <= n; i++) f[i][0] = fat[i];
  int j;
  for (j = 1; (1 << j) < n; j++) {
    for (int i = 1; i <= n; i++) {
      f[i][j] = f[f[i][j - 1]][j - 1];
    }
  }
  Lev = j;
  for (int i = 0; i < q; i++) {
    int a, b;
    Read(a);
    Read(b);
    if (que[b].empty()) {
      Out(0);
      puts("");
      continue;
    }
    int ber = que[b].back();
    int sa = us.gets(a);
    int sb = us.gets(ber);
    int lc = a;
    if (sa == sb) lc = lca(a, ber);
    if (topo[a] >= topo[ber] || sa != sb || (lc != a && lc != ber)) {
      Out(0);
      puts("");
    } else {
      Out(siz[lc]);
      puts("");
    }
  }
  return 0;
}
