/*
* Problem :: 4256 / 트리
*
* Kind :: Data Structure
*
* Insight
* - 전위순회 결과
* 3 6 5 4 8 7 1 2
* 중위순회 결과
* 5 6 8 4 3 1 2 7
* + 전위순회한 결과에서 가장 처음에 만나는 노드는 루트(Root)노드일 수밖에 없다
* 따라서 루트노드는 3 이다
* # 중위순회한 결과에서
* 3 왼쪽에 있는 노드들은 5 6 8 4 이며 이들은 루트노드의 왼쪽 서브트리를 이루는 노드들이다
* 3 오른쪽에 있는 노드들은 1 2 7 이며 이들은 루트노드의 오른쪽 서브트리를 이루는 노드들이다
* -> 왼쪽 서브트리를 이루는 노드의 개수는 총 4개이며
* 이에 해당하는 전위순회 결과는 3 바로 오른쪽 4개의 노드들인 6 5 4 8 에 해당한다
* 오른쪽 서브트리를 이루는 노드의 개수는 총 3개이며
* 이에 해당하는 전위순회 결과는 왼쪽 서브트리를 전위순회한 결과의
* 오른쪽 3개의 노드들인 1 2 7 에 해당한다
* => 그럼 우리는
* 왼쪽 서브트리에 해당하는
* 전위순회 결과
* 6 5 4 8
* 중위순회 결과
* 5 6 8 4
* 를 통해 그 서브트리에서 루트노드를 찾을 수 있다
* => 마찬가지로
* 오른족 서브트리에 해당하는
* 전위순회 결과
* 7 1 2
* 후위순회 결과
* 1 2 7
* 를 통해 그 서브트리에서 루트노드를 찾을 수 있다
*
* - 추가적으로 루트노드의 왼쪽 서브트리의 경우를 살펴보자
* + 전위순회 결과
* 6 5 4 8
* 중위순회 결과
* 5 6 8 4
* # 현재노드 : 6
* 왼쪽 서브트리 중위순회 결과 : 5
* 오른쪽 서브트리 중위순회 결과 : 8 4
* 왼쪽 서브트리 전위순회 결과 : 5
* 오른쪽 서브트리 중위순회 결과 : 4 8
* -> 현재 전위순회 결과에서 루트노드를 알아내고
* 중위순위 결과를 통해 왼쪽 서브트리와 오른쪽 서브트리의
* 전위순회, 중위순회 결과를 알아내서 차례로 방문하는
* 재귀함수를 만들자!
*
* Point
* - 전위순회나 중위순회나 후위순회나
* 사실 방문하는 노트의 순서는 모두 같다
* + 다만, 각 재귀함수에서 출력하는 코드가
* 방문하자마자 그 노드를 출력하는지
* 왼쪽 서브트리를 방문하고 출력하는지
* 왼쪽, 오른쪽 서브트리를 모두 방문하고 출력하는지
* 차이만 있을 뿐이다
*
* - 전위순회 결과와 중위순회 결과만 따로 뽑아내서
* 재귀함수의 인자로 넣어주면 좋겠지만...
* 조금 번거롭다
* + 인덱스로도 충분히 다루어줄 수 있으니 그렇게 해주자
*/
//
// BOJ
// ver.C++
//
// Created by GGlifer
//
// Open Source
#include <iostream>
using namespace std;
#define endl '\n'
// Set up : Global Variables
int N;
int P[1000], I[1000], O[1000];
// Set up : Functions Declaration
void postorder(int sp, int ep, int si, int ei);
int main()
{
// Set up : I/O
ios::sync_with_stdio(false);
cin.tie(nullptr);
// Set up : Input
int T; cin >> T;
while (T--) {
cin >> N;
for (int i=0; i<N; i++)
cin >> P[i]; /* 전위순회 결과 */
for (int i=0; i<N; i++) {
cin >> I[i]; /* 중위순회 결과 */
O[I[i]] = i; /* O[i] = i번 노드의 중위순회 결과 인덱스 */
}
// Control : Output
postorder(0, N-1, 0, N-1);
cout << endl;
}
}
// Helper Functions
void postorder(int sp, int ep, int si, int ei)
/* 전위순회 결과 : P[sp] ~ P[ep]
* 중위순회 결과 : O[si] ~ O[ei]
* 이를 통해 현재노드를 찾고
* 루트노드의 왼쪽 서브트리와 오른쪽 서브트리를 방문 후
* 현재 트리의 루트노드를 출력 (후위순회) */
{
int v = P[sp]; /* node */
int idx = O[v];
int ln = idx - si;
int rn = ei - idx;
/* 왼쪽 서브트리
* 전위순회 결과 : P[lsp] ~ P[lep]
* 중위순회 결과 : O[lsi] ~ O[lei] */
int lsp = sp+1, lep = sp+ln, lsi = si, lei = idx-1;
if (lsp <= lep && lsi <= lei) /* v.left != Ø */
postorder(lsp, lep, lsi, lei);
/* 오른쪽 서브트리
* 전위순회 결과 : P[rsp] ~ R[rep]
* 중위순회 결과 : O[rsi] ~ O[rei] */
int rsp = ep-rn+1, rep = ep, rsi = idx+1, rei = ei;
if (rsp <= rep && rsi <= rei) /* v.right != Ø */
postorder(rsp, rep, rsi, rei);
cout << v << ' '; /* printf(id number of v); */
}