#include<vector>
#include<unordered_map>
#include<algorithm>
class Compression {
public:
    Compression(const std::vector<int>& list) : value_(list) {
        std::sort(begin(value_), end(value_));
        value_.erase(std::unique(begin(value_), end(value_)), end(value_));
        for(int i = 0; i < value_.size(); ++i) index_[value_[i]] = i;
    }
    int size() const {return value_.size();}
    int index(const int v) const {return index_.at(v);}
    int operator[](const int i) const {return value_.at(i);}
private:
    std::unordered_map<int, int> index_;
    std::vector<int> value_;
};

#include<bits/stdc++.h>
using namespace std;

enum {BLANK = -2, WALL};
enum {Y, X};
const int NEXT[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

struct Wall {int px, py, qx, qy;};
struct Query {int sx, sy, gx, gy;};

int range(int x, int lower, int upper) {return max(lower, min(upper, x));}

void flood_fill(vector<vector<int>>& field, int y, int x, int color) {
  const int h = field.size();
  const int w = field.front().size();
  field[y][x] = color;
  for(const auto& d: NEXT) {
    int ny = y + d[Y];
    int nx = x + d[X];
    if(ny < 0 || h <= ny || nx < 0 || w <= nx) continue;
    if(field[ny][nx] == BLANK) flood_fill(field, ny, nx, color);
  }
}

int main() {
  int W, H, M;
  cin >> W >> H >> M;
  W *= 2; H *= 2;

  vector<int> raw_x({0, W}), raw_y({0, H});

  vector<Wall> wall(M);
  for(auto& w: wall) {
    cin >> w.px >> w.py >> w.qx >> w.qy;
    w.px *= 2; w.py *= 2;
    w.qx *= 2; w.qy *= 2;
    for(int d: {-1, 0, 1}) {
      raw_x.insert(begin(raw_x), {range(w.px + d, 0, W), range(w.qx + d, 0, W)});
      raw_y.insert(begin(raw_y), {range(w.py + d, 0, H), range(w.qy + d, 0, H)});
    }
  }

  int Q;
  cin >> Q;
  vector<Query> query(Q);
  for(auto& q: query) {
    cin >> q.sx >> q.sy >> q.gx >> q.gy;
    q.sx *= 2; q.sy *= 2;
    q.gx *= 2; q.gy *= 2;
    raw_x.insert(begin(raw_x), {q.sx, q.gx});
    raw_y.insert(begin(raw_y), {q.sy, q.gy});
  }

  Compression x(raw_x), y(raw_y);

  vector<vector<int>> field(y.size(), vector<int>(x.size(), BLANK));
  for(int i = 0; i < y.size(); ++i) field[i][0] = field[i][x.size() - 1] = WALL;
  for(int j = 0; j < x.size(); ++j) field[0][j] = field[y.size() - 1][j] = WALL;
  for(const auto& w: wall) {
    if(w.px != w.qx) for(int j = x.index(min(w.px, w.qx)); j <= x.index(max(w.px, w.qx)); ++j) field[y.index(w.py)][j] = WALL;
    if(w.py != w.qy) for(int i = y.index(min(w.py, w.qy)); i <= y.index(max(w.py, w.qy)); ++i) field[i][x.index(w.px)] = WALL;
  }

  // 塗りつぶし
  int color = 0;
  for(int i = 0; i < y.size(); ++i) for(int j = 0; j < x.size(); ++j) {
    if(field[i][j] == BLANK) flood_fill(field, i, j, color++);
  }

  // ワーシャルフロイド
  const int INF = 1000000000;
  const int NEXTNEXT[4][2] = {{-2, 0}, {2, 0}, {0, -2}, {0, 2}};
  vector<vector<int>> cost(color, vector<int>(color, INF));
  for(int v = 0; v < color; ++v) cost[v][v] = 0;
  for(int i = 0; i < y.size(); ++i) for(int j = 0; j < x.size(); ++j) {
    if(field[i][j] == WALL) continue;
    for(const auto& d: NEXTNEXT) {
      int ny = i + d[Y];
      int nx = j + d[X];
      if(ny < 0 || y.size() <= ny || nx < 0 || x.size() <= nx) continue;
      int u = field[i][j];
      int v = field[ny][nx];
      if(v == WALL) continue;
      if(u == v) continue;
      cost[u][v] = cost[v][u] = 1;
    }
  }
  for(int k = 0; k < color; ++k) for(int u = 0; u < color; ++u) for(int v = 0; v < color; ++v)
    cost[u][v] = min(cost[u][v], cost[u][k] + cost[k][v]);

  for(const auto& q: query) {
    cout << cost[field[y.index(q.sy)][x.index(q.sx)]][field[y.index(q.gy)][x.index(q.gx)]] << endl;
  }
}

Measured memory_bytes: 7068