#include <bits/stdc++.h>

using namespace std;
typedef long long int ll;
typedef pair<int, int> P;
typedef pair<ll, ll> Pll;
typedef vector<int> Vi;
//typedef tuple<int, int, int> T;
#define FOR(i,s,x) for(int i=s;i<(int)(x);i++)
#define REP(i,x) FOR(i,0,x)
#define ALL(c) c.begin(), c.end()
#define DUMP( x ) cerr << #x << " = " << ( x ) << endl
#define UNIQUE(c) sort(ALL(c)), c.erase(unique(ALL(c)), c.end())

const int dr[4] = {-1, 0, 1, 0};
const int dc[4] = {0, 1, 0, -1};

template <typename T>
struct Data {
  using type = T;
  type data;

  Data(type data) : data(data) {}
  static bool compare (const Data<type> &data1, const Data<type> &data2, size_t base) {
    const size_t dim = data1.data.size();
    for (size_t i = 0; i < dim; i++) {
      if (data1.data[(i + base) % dim] != data2.data[(i + base) % dim]) {
        return data1.data[(i + base) % dim] < data2.data[(i + base) % dim];
      }
    }
    return false;
  }
  bool operator==(const Data<type> &data) const {
    return this->data == data.data;
  }
};

struct KDTreeNode {
  /// The axis for splitting
  size_t axis;
  /// The index of data for splitting
  size_t idx;
  /// Children of the node
  KDTreeNode *left, *right;
};

template <typename T>
struct Region {
  T low, high;
  Region(T low, T high) : low(low), high(high) {};
  bool include(T data) const {
    size_t dim = this->low.size();
    for (size_t i = 0; i < dim; i++) {
      if (data[i] < low[i] or high[i] < data[i]) {
        return false;
      }
    }
    return true;
  }
  bool include(Region<T> region) const {
    size_t dim = this->low.size();
    for (size_t bit = 0; bit < (1U << dim); bit++) {
      T data;
      for (size_t i = 0; i < dim; i++) {
        if (bit >> i & 1) {
          data[i] = region.low[i];
        } else {
          data[i] = region.high[i];
        }
      }
      if (not this->include(data)) {
        return false;
      }
    }
    return true;
  }

  bool overlap(Region<T> region) const {
    size_t dim = this->low.size();
    for (size_t bit = 0; bit < (1U << dim); bit++) {
      T data;
      for (size_t i = 0; i < dim; i++) {
        if (bit >> i & 1) {
          data[i] = region.low[i];
        } else {
          data[i] = region.high[i];
        }
      }
      if (this->include(data)) {
        return true;
      }
    }
    return false;
  }

  friend ostream& operator<<(ostream& os, const Region<T> &region) {
    for (size_t i = 0; i < region.low.size(); i++) {
      if (i > 0) {
        os << 'x';
      }
      os << '[' << region.low[i] << ',' << region.high[i] << ']';
    }
    return os;
  }
};


template <typename DataType>
struct KDtree {
  using T = typename DataType::type;
  using VT = typename T::value_type;
  size_t dim;
  size_t leaf_dim;
  std::vector<DataType> data;
  VT min_range, max_range;
  KDTreeNode *root;

  KDtree(size_t dim = 2, VT min_range = std::numeric_limits<VT>::min(), VT max_range = std::numeric_limits<VT>::max()) : dim(dim), min_range(min_range), max_range(max_range) {}

  KDTreeNode *create_node(size_t axis, size_t idx) {
    KDTreeNode *node = (KDTreeNode *)malloc(sizeof(KDTreeNode));
    if (node == NULL) {
      return NULL;
    }
    node->axis = axis;
    node->idx = idx;
    node->left = node->right = NULL;
    return node;
  }

  KDTreeNode *build(std::vector<std::vector<size_t>> data, size_t depth) {
    if (data[0].size() == 1) {
      return create_node(leaf_dim, data[0][0]);
    } else {
      std::vector<std::vector<size_t>> left_data(this->dim), right_data(this->dim);
      size_t median_idx = static_cast<size_t>(static_cast<int>(data[0].size() - 1) / 2);
      size_t median = data[depth % this->dim][median_idx];
      for (size_t i = 0; i < this->dim; i++) {
        for (size_t j : data[i]) {
          if (this->data[j] == this->data[median] or
              DataType::compare(this->data[j], this->data[median], depth % this->dim)) {
            left_data[i].emplace_back(j);
          } else {
            right_data[i].emplace_back(j);
          }
        }
      }
      assert(left_data[0].size() > 0 and right_data[0].size() > 0);
      KDTreeNode *node = create_node(depth % this->dim, median);
      node->left = build(left_data, depth + 1);
      node->right = build(right_data, depth + 1);
      return node;
    }
  }

  void build_kd_tree(std::vector<DataType> &data) {
    assert(data.size() > 0);

    this->data = data;
    this->leaf_dim = this->dim;

    std::vector<std::vector<size_t>> _data(this->dim, std::vector<size_t>(data.size()));
    for (size_t i = 0; i < this->dim; i++) {
      std::iota(_data[i].begin(), _data[i].end(), 0);
      sort(_data[i].begin(), _data[i].end(),
           [&](const size_t &a, const size_t &b) {
             return DataType::compare(this->data[a], this->data[b], i);
           });
    }
    this->root = build(_data, 0);
  }

  void report_subtree(KDTreeNode *node, std::vector<size_t> &output) const {
    if (node->axis == this->leaf_dim) {
      output.emplace_back(node->idx);
    } else {
      report_subtree(node->left, output);
      report_subtree(node->right, output);
    }
  }

  std::vector<size_t> range_query(Region<T> query_region) {
    T node_low, node_high;
    node_low.fill(this->min_range);
    node_high.fill(this->max_range);
    Region<T> node_region(node_low, node_high);
    std::vector<size_t> output;
    query(this->root, query_region, node_region, output);
    return output;
  }

  void query(KDTreeNode *node, Region<T> query_region, Region<T> node_region, std::vector<size_t> &output) {
    T data = this->data[node->idx].data;
    if (node->axis == this->leaf_dim) {
      if (query_region.include(data)) {
        output.emplace_back(node->idx);
      }
    } else {
      Region<T> left_region = node_region, right_region = node_region;
      Region<T> left_query_region = query_region, right_query_region = query_region;

      left_region.high[node->axis] = data[node->axis];
      right_region.low[node->axis] = data[node->axis];
      if (query_region.low[node->axis] <= data[node->axis] and data[node->axis] < query_region.high[node->axis]) {
        left_query_region.high[node->axis] = data[node->axis];

      }
      if (data[node->axis] <= query_region.high[node->axis] and query_region.low[node->axis] < data[node->axis]) {
        right_query_region.low[node->axis] = data[node->axis];

      }
      if (left_query_region.include(left_region)) {
        report_subtree(node->left, output);
      } else if (left_region.overlap(left_query_region)) {
        query(node->left, left_query_region, left_region, output);
      }

      if (right_query_region.include(right_region)) {
        report_subtree(node->right, output);
      } else if (right_region.overlap(right_query_region)) {
        query(node->right, right_query_region, right_region, output);
      }
    }
  }

  void output() {
    output_kdtree(this->root);
  }

  void output_kdtree(KDTreeNode *node) {
      std::cout << "idx: " << node->idx << ", (";
      for (size_t i = 0; i < this->dim; i++) {
        if (i > 0) {
          std::cout << ',';
        }
        std::cout << this->data[node->idx].data[i];
      }
      std::cout << ") ";
    if (node->axis != this->leaf_dim) {
      std::cout << "(left, right) = (" << node->left->idx << ',' << node->right->idx << ')' << std::endl;
      output_kdtree(node->left);
      output_kdtree(node->right);
    } else {
      std::cout << std::endl;
    }
  }
};

int main() {
  using DataType = Data<std::array<int, 2>>;
  KDtree<DataType> kdtree;
  std::vector<DataType> points;
  int N; scanf("%d", &N);
  REP(i, N) {
    int x, y; scanf("%d %d", &x, &y);
    DataType::type tmp = {x, y};
    points.emplace_back(DataType(tmp));
  }
  kdtree.build_kd_tree(points);

  int Q; scanf("%d", &Q);
  REP(i, Q) {
    int sx, tx, sy, ty; scanf("%d %d %d %d", &sx, &tx, &sy, &ty);
    DataType::type low = {sx, sy}, high = {tx, ty};
    Region<DataType::type> query_region(low, high);
    std::vector<size_t> out = kdtree.range_query(query_region);
    sort(ALL(out));
    for (size_t i : out) printf("%d\n", i);
    printf("\n");
  }

  return 0;
}



Measured memory_bytes: 94980