/*
* Problem :: 11067 / 모노톤길
*
* Kind :: Math
*
* Insight
* - 모노톤길의 특성
* + x 좌표가 작은 카페부터 들른다
* + i 번째 카페의 x 좌표와 i+1 번째 카페의 x 좌표가 서로 다르면
* i 번째 카페의 y 좌표와 i+1 번째 카페의 y 좌표가 서로 같아야 한다
* + x 좌표가 같은 카페들의 순서는
* y 좌표가 증가하는 순서이거나 감소하는 순서이다
*
* - 일단 주어진 카페들의 좌표를
* x 좌표가 증가하는 순서, x 좌표가 같으면 y 좌표로 증가하는 순서로 정렬해보자
* + ... (2,1) -> (3,1) -> [(3,3) -> (5,-1)] -> (5,1) -> (5,3) -> (6,-1) -> ..
* x 좌표가 달라질 때는 y 좌표가 같아야 한다
* # 이때 달라진 x 좌표를 기준으로 같은 x 좌표에 있는 카페들을
* y 좌표가 감소하는 순서로 바꾸어 주자!
* -> x 좌표가 증가하는 순서, x 좌표가 같으면 y 좌표가 증가하는 순서로 정렬했을 때
* (o = 카페, 왼쪽 숫자 = y 좌표, 아래 숫자 = x 좌표)
*
* 4 o o
* | \ | \
* 3 o | | |
* | | | |
* 2 o - o \ o |
* | | | |
* 1 o - o - o | | |
* | | |
* \ | \
* -1 o o
* 0 1 2 3 5 6
*
* -> x 좌표가 달라질 때 달라진 x 좌표를 기준으로 같은 x 좌표에 있는 카페들을
* y 좌표가 감소하는 순서로 바꾸어 주었을 때
* (o = 카페, 왼쪽 숫자 = y 좌표, 아래 숫자 = x 좌표)
*
* 4 o - - - o
* | |
* 3 o |
* | |
* 2 o - o o
* | |
* 1 o - o - o |
* |
* |
* -1 o - o
* 0 1 2 3 5 6
*
* Point
* - 산책로는 항상 존재한다 <= 모노톤길이 항상 존재한다
*
* - 시작이 항상 (0,0) 이다
* + x 좌표가 0 이고 y 좌표가 음수인 카페가 주어지는 경우를 고려해주어야 한다
* # (0,0), (0,-1), (0,-2) 가 주어진다면
* 정렬할 때 (0,-2) -> (0,-1) -> (0,0) 이 된다
* -> (0,0) -> (0,-1) -> (0,-2) 로 뒤집어 주어야 하는데
* 이를 (-1, 0) 이라는 가상의 카페가 처음 시작때 존재한다고 가정하여 해결하였다
*
* - vector<int> A = {1, 2, 3};
* reverse(A.begin(), A.begin()+2);
* // A = {2, 1, 3}
*/
//
// BOJ
// ver.C++
//
// Created by GGlifer
//
// Open Source
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define endl '\n'
// Set up : Global Variables
struct Cafe { int x, y; };
// Set up : Functions Declaration
bool operator < (const Cafe &u, const Cafe &v);
int main()
{
// Set up : I/O
ios::sync_with_stdio(false);
cin.tie(nullptr);
// Set up : Input
int T; cin >> T;
while (T--) {
int N; cin >> N;
vector<Cafe> cafes(N+1);
for (int i=1; i<=N; i++) {
cin >> cafes[i].x >> cafes[i].y;
}
// Process
cafes[0] = {-1, 0}; /* Off by one error 해결을 위한 가상의 시작 카페 설정 */
/* x 좌표가 증가하는 순서, x 좌표가 같으면 y 좌표가 증가하는 순서대로 정렬
* 주어지는 카페들의 x 좌표는 0 이상이기 때문에
* 항상 가상의 시작 카페가 cafes[0] 이 된다 */
sort(cafes.begin(), cafes.end());
int idx = 1; /* 시작 인덱스 */
while (idx <= N) {
/* 현재 카페와 이전 카페의 x 좌표가 같으면 */
if (cafes[idx].x == cafes[idx-1].x) {
idx++; /* 올바른 모노톤길을 걷고 있음(수직 구간), 다음 카페 탐색 */
} /* 현재 카페와 이전 카페의 x 좌표가 다를 때,
* 현재 카페와 이전 카페의 y 좌표가 같으면 */
else if (cafes[idx].y == cafes[idx-1].y) {
idx++; /* 올바른 모노톤길을 걷고 있음(수평 구간), 다음 카페 탐색 */
} /* 현재 카페와 이전 카페의 x 좌표와 y 좌표가 모두 다르면 */
else { /* 올바른 모노톤길이 아님
* 현재 카페의 x 좌표를 기준으로 같은 x 좌표에 있는 카페들을
* y 좌표가 감소하는 순서로 만들어줌
* 즉, 현재 y 좌표가 증가하는 순서로 되어있으니
* 카페들의 순서를 뒤집어줌으로써 y 좌표가 감소하는 순서로 만들어줌 */
auto spos = cafes.begin() + idx; /* 현재 카페의 위치 */
int x = cafes[idx].x; /* 현재 카페의 x 좌표 */
/* 현재 카페의 x 좌표와 같지 않은 x 좌표를 가진 카페를 만날 때까지 탐색 */
while (++idx <= N && x == cafes[idx].x) {}
/* 현재 카페의 x 좌표가 아닌 카페들 중 처음만난 카페의 위치 */
auto epos = cafes.begin() + idx;
reverse(spos, epos); /* 뒤집어줌 */
}
}
// Control : Output
int M; cin >> M;
/* 현재 정렬된 위치가 카페의 번호가 됨 */
for (int i=0; i<M; i++) {
int k; cin >> k;
cout << cafes[k].x << ' ' << cafes[k].y << endl;
}
}
}
// Helper Functions
bool operator < (const Cafe &u, const Cafe &v)
/* 카페 구조체 비교를 위한 함수 */
/* x 좌표가 증가하는 순서, x 좌푝 같으면 y 좌표가 증가하는 순서로 정렬 */
{
return make_pair(u.x, u.y) < make_pair(v.x, v.y);
}