#include<cstdio>
#include<algorithm>
#include<vector>

using namespace std;

// 2分探索木内の各ノードの情報を保持するクラス
class Node
{
    public:
        int location;  // 要素全体の位置 ( 昇順に並べた時 )
        int p, l, r;
        // コンストラクタ
        Node() {}
};

// 点の集合の情報を保持するクラス
class Point
{
    public:
        int id, x, y;

        Point() {}
        // メンバ変数の初期化
        Point(int id, int x, int y): id(id), x(x), y(y) {}

        // 演算子のオーバーロード ( constメンバ関数 : メンバ変数の変更を禁止する)
        // main() 内の sort() で使用する
        bool operator < (const Point &p) const
        {
            return id < p.id;
        }

        void print()
        {
            // cout より高速な　printf 関数を使用
            printf("%d\n", id);
        }
};

static const int MAX = 1000000;
static const int NIL = -1;

int N;
Point P[MAX];
Node T[MAX];
int np;

// makeKDTree() 内の sort()のための比較関数
bool lessX(const Point &p1, const Point &p2) { return p1.x < p2.x; }
bool lessY(const Point &p1, const Point &p2) { return p1.y < p2.y; }

// ２分木を作成する関数
int makeKDTree(int l, int r, int depth)
{
    if ( !( l < r ) )
    {
        return NIL;
    }

    // 中央値の演算
    int mid = ( l + r ) / 2;
    // ノードNo.
    int t = np++;

    // 木の深さによって、ソートする軸を変更する
    if ( depth % 2 == 0 )
    {
        // 配列 P で, Xの要素について昇順にソートする
        // lessX : 比較関数
        sort(P + l, P + r, lessX);
    }
    else
    {
        // 配列 P で, Yの要素について昇順にソートする
        // lessY : 比較関数
        sort(P + l, P + r, lessY);
    }

    // 要素全体における位置
    T[t].location = mid;
    // 左部分木の作成
    T[t].l = makeKDTree(l, mid, depth + 1);
    // 右部分木の作成
    T[t].r = makeKDTree(mid + 1, r, depth + 1);

    return t;
}

// 要素を検索するための関数
// v      : 根の要素No.
// sx〜ty : 検索する範囲
// depth  : 木の深さ
//　ans   : 条件に合う要素を格納するvector
void find(int v, int sx, int tx, int sy, int ty, int depth, vector<Point> &ans)
{
    int x = P[T[v].location].x;
    int y = P[T[v].location].y;

    if ( sx <= x && x <= tx && sy <= y && y <= ty )
    {
        // 条件を満たす点が見つかった
        ans.push_back(P[T[v].location]);
    }

    if (depth % 2 == 0)
    {
        // ------------------------------
        // 木の深さが偶数の時 : xについて探索
        // ------------------------------
        if ( T[v].l != NIL )
        {
            if ( sx <= x )
            {
                // 左部分木を探索
                find(T[v].l, sx, tx, sy, ty, depth + 1, ans);
            }
        }

        if ( T[v].r != NIL )
        {
            if ( x <= tx )
            {
                // 右部分木を探索
                find(T[v].r, sx, tx, sy, ty, depth + 1, ans);
            }
        }
    }
    else
    {
        // ------------------------------
        // 木の深さが奇数の時 : yについて探索
        // ------------------------------
        if ( T[v].l != NIL )
        {
            if ( sy <= y )
            {
                // 左部分木を探索
                find(T[v].l, sx, tx, sy, ty, depth + 1, ans);
            }
        }

        if ( T[v].r != NIL )
        {
            if ( y <= ty )
            {
                // 右部分木を探索
                find(T[v].r, sx, tx, sy, ty, depth + 1, ans);
            }
        }
    }

    return;
}

// メイン関数
int main(void)
{
    int x, y;

    scanf("%d", &N);

    for (int i = 0; i < N; i++)
    {
        // cin より高速な scanf 関数を使用
        scanf("%d %d", &x, &y);
        // 各要素の設定
        P[i] = Point(i, x, y);
        T[i].l = T[i].r = T[i].p = NIL;
    }

    np = 0;

    // 2分探索木の作成
    int root = makeKDTree(0, N, 0);

    int q;
    scanf("%d", &q);
    int sx, tx, sy, ty;
    vector<Point> ans;

    for (int i = 0; i < q; i++)
    {
        scanf("%d %d %d %d", &sx, &tx, &sy, &ty);
        // vector要素の初期化
        ans.clear();
        // 要素の検索
        find(root, sx, tx, sy, ty, 0, ans);
        // 見つかった結果を id の昇順にソートする
        sort(ans.begin(), ans.end());

        for (int j = 0; j < ans.size(); j++)
        {
            // 結果の表示
            ans[j].print();
        }

        printf("\n");
    }

    return 0;
}



Measured memory_bytes: 15952