import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author sheep
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		SoapTime solver = new SoapTime();
		solver.solve(1, in, out);
		out.close();
	}
}

class SoapTime {

    class Point implements Comparable<Point> {
        public int x, y;
        int dist;

        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }

        private int sign(int x) {
            return Integer.signum(x);
        }

        public int compareTo(Point arg0) {
            if (x != arg0.x) {
                return sign(x - arg0.x);
            }

            return sign(y - arg0.y);
        }
    }

	public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt();
        int m = in.nextInt();

        Point man[] = new Point[n];
        Point station[] = new Point[m];

        for (int i = 0; i < n; ++i) {
            int x = in.nextInt();
            int y = in.nextInt();
            man[i] = new Point((x + y) * 2, (x - y) * 2);
        }

        for (int i = 0; i < m; ++i) {
            int x = in.nextInt();
            int y = in.nextInt();
            station[i] = new Point((x + y) * 2, (x - y) * 2);
        }

        {
            Event events[] = new Event[n + m];
            for (int i = 0; i < n; ++i) {
                events[i] = new Event(man[i].x, man[i].y, i);
            }

            for (int i = 0; i < m; ++i) {
                events[i + n] = new Event(station[i].x, station[i].y);
            }

            int distToStation[] = findDistToStation(events, n);

            for (int i = 0; i < n; ++i) {
                man[i].dist = distToStation[i];
            }

            Arrays.sort(man, new Comparator<Point>() {
                @Override
                public int compare(Point o1, Point o2) {
                    return o1.dist - o2.dist;
                }
            });
        }

        int ans = man[n - 1].dist;

        int x1[] = new int[n];
        int y1[] = new int[n];
        int x2[] = new int[n];
        int y2[] = new int[n];

        x1[n - 1] = man[n - 1].x;
        y1[n - 1] = man[n - 1].y;
        x2[n - 1] = man[n - 1].x;
        y2[n - 1] = man[n - 1].y;

        for (int i = n - 2; i >= 0; --i) {
            x1[i] = Math.min(man[i].x, x1[i + 1]);
            x2[i] = Math.max(man[i].x, x2[i + 1]);
            y1[i] = Math.min(man[i].y, y1[i + 1]);
            y2[i] = Math.max(man[i].y, y2[i + 1]);
        }

        int leastTime[] = new int[n];
        for (int i = 0; i < n; ++i) {
            leastTime[i] = Math.max(x2[i] - x1[i], y2[i] - y1[i]) / 2;
            x1[i] += leastTime[i];
            x2[i] -= leastTime[i];
            y1[i] += leastTime[i];
            y2[i] -= leastTime[i];
        }

        ans = Math.min(ans, leastTime[0]);

        Event events[] = new Event[n * 4 + m];
        for (int i = 0; i < n; ++i) {
            events[4 * i + 0] = new Event(x1[i], y1[i], i);
            events[4 * i + 1] = new Event(x1[i], y2[i], i);
            events[4 * i + 2] = new Event(x2[i], y1[i], i);
            events[4 * i + 3] = new Event(x2[i], y2[i], i);
        }

        for (int i = 0; i < m; ++i) {
            events[4 * n + i] = new Event(station[i].x, station[i].y);
        }

        int disStationToRectangle[] = findDistToStation(events, n);

        RectangleEvent rectEvents[] = new RectangleEvent[n + m];
        for (int i = 0; i < n; ++i) {
            rectEvents[i] = new RectangleEvent(x1[i], y1[i], x2[i], y2[i], i);
        }

        for (int i = 0; i < m; ++i) {
            rectEvents[n + i] = new RectangleEvent(station[i].x, station[i].y);
        }

        int disStationToRectangle2[] = findRectangleDistToStation(rectEvents, n);
        for (int i = 0; i < n; ++i) {
            disStationToRectangle[i] = Math.min(disStationToRectangle2[i], disStationToRectangle[i]);
        }

        for (int i = n - 1; i > 0; --i) {
            if (x1[i] <= x2[i] && y1[i] <= y2[i]) {
                if (man[i - 1].dist == Integer.MAX_VALUE || disStationToRectangle[i] == Integer.MAX_VALUE) {
                    continue;
                }

                int need = man[i - 1].dist + leastTime[i] + disStationToRectangle[i];
                need = (need + 1) / 2;
                need = Math.max(need, man[i - 1].dist);
                need = Math.max(leastTime[i], need);

                ans = Math.min(ans, need);
            }  else {
                break;
            }
        }

        out.println((ans + 1) / 2);
    }

    private int[] findRectangleDistToStation(RectangleEvent events[], int n) {
        int ret[] = new int[n];
        Arrays.fill(ret, Integer.MAX_VALUE);

        int tmp[] = new int[events.length * 2];

        for (int dir = 0; dir < 4; ++dir) {

            for (int i = 0; i < events.length; ++i) {
                tmp[i * 2] = events[i].x1;
                tmp[i * 2 + 1] = events[i].x2;
            }

            Order order = new Order(tmp);
            for (RectangleEvent e : events) {
                e.realX1 = order.get(e.x1);
                e.realX2 = order.get(e.x2);
            }

            IntervalTree tree = new IntervalTree(order.size());
            Arrays.sort(events);

            for (RectangleEvent e : events) {
                if (e.type == 0) {
                    tree.insert(e.realX1, e.y1);
                } else {
                    int l = Math.min(e.realX1, e.realX2);
                    int r = Math.max(e.realX2, e.realX1);
                    int max = tree.getMaxValue(l, r);
                    if (max == Integer.MIN_VALUE) {
                        continue;
                    }

                    if (max >= Math.min(e.y1, e.y2)) {
                        ret[e.updateId] = 0;
                    } else {
                        ret[e.updateId] = Math.min(ret[e.updateId], Math.min(e.y1, e.y2) - max);
                    }
                }
            }

            for (RectangleEvent e : events) {
                e.rotate();
            }
        }

        return ret;
    }

    private int[] findDistToStation(Event events[], int n) {
        int ret[] = new int[n];
        for (Event e : events) {
            int x = e.x;
            int y = e.y;
            e.x = (x + y);
            e.y = (x - y);
        }
        Arrays.fill(ret, Integer.MAX_VALUE);
        int tmp[] = new int[events.length];

        for (int step = 0; step < 4; ++step) {

            int ptr = 0;
            for (Event e : events) {
                tmp[ptr++] = e.x;
            }
            Order order = new Order(tmp);
            for (Event e : events) {
                e.queryX = order.get(e.x);
            }

            IntervalTree tree = new IntervalTree(order.size());
            Arrays.sort(events);

            for (Event e : events) {
                if (e.type == 0) {
                    tree.insert(e.queryX, e.x + e.y);
                } else {
                    int max = tree.getMaxValue(0, e.queryX);
                    if (max == Integer.MIN_VALUE) {
                        continue;
                    }
                    int delta = (e.x + e.y - max) / 2;
                    if (delta < ret[e.id]) {
                        ret[e.id] = delta;
                    }
                }
            }

            for (Event e : events) {
                int t = e.y;
                e.y = -e.x;
                e.x = t;
            }
        }

        return ret;
    }

    class RectangleEvent implements Comparable<RectangleEvent>{
        int type;
        int x1, y1, x2, y2;
        int realX1, realX2;
        int updateId;

        void rotate() {
            int t = y1;
            y1 = -x1;
            x1 = t;

            t = y2;
            y2 = -x2;
            x2 = t;
        }

        RectangleEvent(int x1, int y1, int x2, int y2, int updateId) {
            this.x1 = x1;
            this.y1 = y1;
            this.x2 = x2;
            this.y2 = y2;
            this.type = 1;
            this.updateId = updateId;
        }

        RectangleEvent(int x, int y) {
            this.x1 = this.x2 = x;
            this.y1 = this.y2 = y;
            this.type = 0;
        }

        public int compareTo(RectangleEvent o) {
            int y = Math.max(y1, y2);
            int oy = Math.max(o.y1, o.y2);
            if (y != oy) {
                return y - oy;
            }

            int x = Math.max(x1, x2);
            int ox = Math.max(o.x1, o.x2);
                if (x != ox) {
                return x - ox;
            }

            return type - o.type;
        }
    }

    class IntervalTree {

        int size;
        int val[];

        IntervalTree(int length) {
            this.size = length;
            val = new int[length * 4 + 100];
            Arrays.fill(val, Integer.MIN_VALUE);
        }

        int getMaxValue(int left, int right, int l, int r, int x) {
            if (l <= left && r >= right) {
                return val[x];
            }
            int mid = (left + right) >> 1;
            int ret = Integer.MIN_VALUE;
            if (l <= mid) ret = getMaxValue(left, mid, l, r, x * 2);
            if (r > mid) ret = Math.max(ret, getMaxValue(mid + 1, right, l, r, x * 2 + 1));
            return ret;
        }

        int getMaxValue(int left, int right) {
             return getMaxValue(0, size - 1, left, right, 1);
        }

        void insert(int left, int right, int pos, int x, int value) {
            if (left == right) {
                val[x] = Math.max(val[x], value);
                return;
            }

            int mid = (left + right) >> 1;
            if (pos <= mid) {
                insert(left, mid, pos, x * 2, value);
            } else {
                insert(mid + 1, right, pos, x * 2 + 1, value);
            }

            val[x] = Math.max(val[x * 2], val[x * 2 + 1]);
        }

        void insert(int pos, int value) {
             insert(0, size - 1, pos, 1, value);
        }

    }

    class Order {

        private int arr[];

        Order(int orig[]) {
            int temp[] = orig.clone();
            Arrays.sort(temp);

            int total = 1;
            for (int i = 1; i < temp.length; ++i)
                if (temp[i] != temp[i - 1])
                    ++total;

            arr = new int[total];
            arr[0] = temp[0];
            total = 1;
            for (int i = 1; i < temp.length; ++i)
                if (temp[i] != temp[i - 1])
                    arr[total++] = temp[i];
        }

        public int size() {
            return arr.length;
        }

        public int get(int x) {
            return Arrays.binarySearch(arr, x);
        }
    }

    class Event implements Comparable<Event> {
        int type;
        int x, y, id;
        int queryX;

        Event(int x, int y, int id) {
            this.x = x;
            this.y = y;
            this.id = id;
            this.type = 1;
        }

        Event(int x, int y) {
            this.x = x;
            this.y = y;
            this.type = 0;
        }

        public int compareTo(Event o) {
            if (y != o.y) {
                return y - o.y;
            }

            if (x != o.x) {
                return x - o.x;
            }

            return type - o.type;
        }
    }
}

class InputReader {
    BufferedReader reader;
    StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    }


#include <bits/stdc++.h>

using namespace std;

#define FOR(i, a, b) for (int i = a; i <= b; i++)
#define FOD(i, a, b) for (int i = a; i >= b; i--)
#define REP(i, a, b) for (int i = a; i < b; i++)
#define DEBUG(X) cout << #X << " = " << X << endl;
#define PR(A, n) {cout << #A << " = "; FOR(_, 1, n) cout << A[_] << " "; cout << endl;}
#define x1 Jug
#define x2 jgu
#define y1 ujg
#define y2 ugj

const int N = 1E5 + 10;
const int INF = 2E8 + 10;

struct Point {
    int x, y;
    Point (int _x = 0, int _y = 0) : x(_x), y(_y) {}
    bool operator < (const Point &other) const {
        return y < other.y;
    }
};

int n, m;
Point a[N], b[N];
vector <int> rar;

struct SegmentTree {
    #define mid (l + r) / 2
    vector <int> val[N * 4];
    void Update(int id, int l, int r, int i, int key) {
        if (i < l || r < i || l > r) return;
        val[id].push_back(key);
        if (l == r) return;
        if (i <= mid) Update(id << 1, l, mid, i, key);
            else Update(id << 1 | 1, mid + 1, r, i, key);
    }
    bool Query(int id, int l, int r, int x1, int x2, int y1, int y2) {
        if (x2 < l || r < x1 || l > r) return 0;
        if (x1 <= l && r <= x2) {
            vector <int> :: iterator it = lower_bound(val[id].begin(), val[id].end(), y1);
            if (it == val[id].end()) return 0;
            return (*it) <= y2;
        }
        return Query(id << 1, l, mid, x1, x2, y1, y2) ||
                Query(id << 1 | 1, mid + 1, r, x1, x2, y1, y2);
    }
    bool Query(int x1, int x2, int y1, int y2) {
        if (x1 > x2 || y1 > y2) return 0;
        x1 = lower_bound(rar.begin(), rar.end(), x1) - rar.begin() + 1;
        x2 = upper_bound(rar.begin(), rar.end(), x2) - rar.begin();
        return Query(1, 1, m, x1, x2, y1, y2);
    }
    #undef mid
} ST;

void Read_Input() {
    #ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif // LOCAL
    scanf("%d%d", &n, &m);
    FOR(i, 1, n) {
        scanf("%d%d", &a[i].x, &a[i].y);
        a[i] = Point(a[i].x - a[i].y, a[i].x + a[i].y);
    }
    FOR(i, 1, m) {
        scanf("%d%d", &b[i].x, &b[i].y);
        b[i] = Point(b[i].x - b[i].y, b[i].x + b[i].y);
        rar.push_back(b[i].x);
    }
}

void BuildTree() {
    sort(b + 1, b + 1 + m);
    sort(rar.begin(), rar.end());
    FOR(i, 1, m) {
        int pos = lower_bound(rar.begin(), rar.end(), b[i].x) - rar.begin() + 1;
        ST.Update(1, 1, m, pos, b[i].y);
    }
}

int dist[N], idx[N];

bool cmp(int x, int y) {
    return dist[x] > dist[y];
}

void FindClosestStation() {
    FOR(i, 1, n) {
        int l = 0, h = INF;
        idx[i] = i; dist[i] = INF;
        while (l <= h) {
            int mid = (l + h) >> 1;
            if (ST.Query(a[i].x - mid, a[i].x + mid, a[i].y - mid, a[i].y + mid)) {
                dist[i] = mid;
                h = mid - 1;
            } else l = mid + 1;
        }
    }
    sort(idx + 1, idx + 1 + n, cmp);
}

bool Check(int len) {
    int x1 = -INF, y1 = -INF;
    int x2 = INF, y2 = INF;
    FOR(jug, 1, n) {
        int i = idx[jug];
        int rem = len - dist[i];
        if (rem >= 0 && ST.Query(x1 - rem, x2 + rem, y1 - rem, y2 + rem))
            return 1;
        x1 = max(x1, a[i].x - len);
        y1 = max(y1, a[i].y - len);
        x2 = min(x2, a[i].x + len);
        y2 = min(y2, a[i].y + len);
        if (x1 > x2 || y1 > y2) return 0;
    }
    return 1;
}

void Solve() {
    int l = 0, h = INF, ans;
    while (l <= h) {
        int mid = (l + h) >> 1;
        if (Check(mid)) {
            ans = mid;
            h = mid - 1;
        } else l = mid + 1;
    }
    printf("%d", ans);
}

int main() {
    Read_Input();
    BuildTree();
    FindClosestStation();
    Solve();
    return 0;
}
//hello


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <limits.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <string>
#include <functional>
#include <vector>
#include <numeric>
#include <deque>
#include <bitset>
#include <iostream>
using namespace std;
typedef long long lint;
typedef long double llf;
typedef pair<int, int> pi;
const int mod = 1e9 + 7;

struct t1{
	int first, second, nsub;
};

int n, m;
t1 a[100005];
pi b[100005];

bool found(int sx, int ex, int sy, int ey){
	for(int i=0; i<m; i++){
		if(a[i].first >= sx && a[i].first <= ex && a[i].second >= sy && a[i].second <= ey){
			return 1;
		}
	}
	return 0;
}

bool ok(int sx, int ex, int sy, int ey, int d2){
	return found(sx-d2, ex+d2, sy-d2, ey+d2);
}

int main(){
	cin >> n >> m;
	for(int i=0; i<n; i++){
		int x, y;
		scanf("%d %d",&x,&y);
		a[i] = {x+y, x-y, -1};
	}
	int ret = 1e9;
	int maxx = -1e9, minx = 1e9, maxy = -1e9, miny = 1e9;
	for(int i=0; i<n; i++){
		maxx = max(maxx, a[i].first);
		minx = min(minx, a[i].first);
		maxy = max(maxy, a[i].second);
		miny = min(miny, a[i].second);
	}
	ret = min(ret, max(maxx-minx+1, maxy-miny+1) / 2);
	if(m == 0){
		printf("%d",ret);
		return 0;
	}
	for(int i=0; i<m; i++){
		int x, y;
		scanf("%d %d",&x,&y);
		b[i] = pi(x+y, x-y);
	}
	for(int i=0; i<n; i++){
		a[i].nsub = 1e9;
		for(int j=0; j<m; j++){
			a[i].nsub = min(a[i].nsub, max(abs(b[j].first - a[i].first), abs(b[j].second - a[i].second)));
		}
	}
	sort(a, a+n, [&](const t1 &a, const t1 &b){
		return a.nsub > b.nsub;
	});
	vector<int> cnd;
	for(int i=0; i<n; i++){
		cnd.push_back(a[i].nsub);
	}
	sort(cnd.begin(), cnd.end());
	cnd.resize(unique(cnd.begin(), cnd.end()) - cnd.begin());
	ret = min(ret, cnd.back());
	reverse(cnd.begin(), cnd.end());
	int pnt = 0;
	int sx = -1e9, ex = 1e9, sy = -1e9, ey = 1e9;
	for(auto &i : cnd){
		while(pnt < n && a[pnt].nsub > i){
			sx = max(sx, a[pnt].first);
			ex = min(ex, a[pnt].first);
			sy = max(sy, a[pnt].second);
			ey = min(ey, a[pnt].second);
			pnt++;
		}
		int s = 0, e = 1e9;
		while(s != e){
			int m = (s+e)/2;
			if(ok(sx-m, ex+m, sy-m, ey+m, m-i)) e = m;
			else s = m+1;
		}
		ret = min(ret, s);
	}
	cout << ret;
}


#include <iostream>
#include <fstream>
#include <string>

#define MAX 100

using namespace std;

int main()
{
	int n, l, a[100], m = 0;
	cin >> n >> l;
	for(int i = 0; i < n; i++)
		cin >> a[i];
	for(int i = l; i < 100; i++)
	{
		int s = 0;
		for(int j = 0; j < n; j++)
			s += a[j] / i;
		if(s * l > m)
			m = s * l;
	}
	cout << m << endl;
	return 0;
}


#include <iostream>
#include <fstream>
#include <string>

#define MAX 100

using namespace std;

int main()
{
	int n, l, a[100], m = 0;
	cin >> n >> l;
	for(int i = 0; i < n; i++)
		cin >> a[i];
	for(int i = l; i <= 100; i++)
	{
		int s = 0;
		for(int j = 0; j < n; j++)
			s += a[j] / i;
		if(s * l > m)
			m = s * l;
	}
	cout << m << endl;
	return 0;
}


#include <iostream>
#include <fstream>
#include <string>

#define MAX 100

using namespace std;

int main()
{
	int n, l, a[100], m = 0;
	cin >> n >> l;
	for(int i = 0; i < n; i++)
		cin >> a[i];
	for(int i = l; i <= 100; i++)
	{
		int s = 0;
		for(int j = 0; j < n; j++)
			s += a[j] / i;
		if(s * i > m)
			m = s * i;
	}
	cout << m << endl;
	return 0;
}


#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <algorithm>
#include <functional>

using namespace std;

#define Size(s) ((int)s.size())
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define FOR(i,n) for(int i=0;i<n;i++)

int area, n, l, al, i, j;
int a[101];

//#include <conio.h>
int main()
{
//    freopen("test.txt","r",stdin);
    cin >> n >> l;
    for (i = 0, j = 0; i < n; i++)
    {
        cin >> al;
        if (al >= l)
        {
               a[j] = al;
               j++;
        }
    }
    int count = 0;
    int maxA = -1;
    sort(a,a+j);
    FOR(k,j)
    {
            count = 0;
            FOR(f,j) count += a[f] / a[k];
            if (maxA < count * a[k]) maxA = count * a[k];
    }
    cout << maxA << endl;
//    getch();
    return 0;
}


#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <algorithm>
#include <functional>

using namespace std;

#define Size(s) ((int)s.size())
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define FOR(i,n) for(int i=0;i<n;i++)
#define FOR2(i,be,en) for(int i=be;i<=en;i++)

int n, l, al, i, j;
int a[101];

//#include <conio.h>
int main()
{
//    freopen("test.txt","r",stdin);
    cin >> n >> l;
    for (i = 0, j = 0; i < n; i++)
    {
        cin >> al;
        if (al >= l)
        {
               a[j] = al;
               j++;
        }
    }
    int count = 0;
    long maxA = 0;
    sort(a,a+j);
    FOR2(k,l,100)
    {
            count = 0;
            FOR(f,j) count += (a[f] / k);
            if (maxA < count * k) maxA = count * k;
    }
    cout << maxA << endl;
//    getch();
    return 0;
}


#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <algorithm>
#include <functional>

using namespace std;

#define Size(s) ((int)s.size())
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define FOR(i,n) for(int i=0;i<n;i++)

int area, n, l, al, i, j;
int a[101];

//#include <conio.h>
int main()
{
//    freopen("test.txt","r",stdin);
    cin >> n >> l;
    int minl = 101;
    for (i = 0, j = 0; i < n; i++)
    {
        cin >> al;
        if (al >= l)
        {
               a[j] = al;
               if (minl > al) minl = al;
               j++;
        }
    }
    int count = 0;
    for (int k = 0; k < j; k++) count += a[k] / l;
    cout << (minl * count) << endl;
//    getch();
    return 0;
}


#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <algorithm>
#include <functional>

using namespace std;

#define Size(s) ((int)s.size())
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define FOR(i,n) for(int i=0;i<n;i++)

int n, l, al, i, j;
int a[101];

//#include <conio.h>
int main()
{
//    freopen("test.txt","r",stdin);
    cin >> n >> l;
    for (i = 0, j = 0; i < n; i++)
    {
        cin >> al;
        if (al >= l)
        {
               a[j] = al;
               j++;
        }
    }
    int count = 0;
    long maxA = 0;
    sort(a,a+j);
    FOR(k,j)
    {
            count = 0;
            FOR(f,j) count += (a[f] / a[k]);
            if (maxA < count * a[k]) maxA = count * a[k];
    }
    cout << maxA << endl;
//    getch();
    return 0;
}


#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <algorithm>
#include <functional>

using namespace std;

#define Size(s) ((int)s.size())
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define FOR(i,n) for(int i=0;i<n;i++)

int area, n, l, al, i, j;
int a[101];

//#include <conio.h>
int main()
{
//    freopen("test.txt","r",stdin);
    cin >> n >> l;
    for (i = 0, j = 0; i < n; i++)
    {
        cin >> al;
        if (al >= l)
        {
               a[j] = al;
               j++;
        }
    }
    int count = 0;
    int maxA = 0;
    sort(a,a+j);
    FOR(k,j)
    {
            count = 0;
            FOR(f,j) count += a[f] / a[k];
            if (maxA < count * a[k]) maxA = count * a[k];
    }
    cout << maxA << endl;
//    getch();
    return 0;
}


# include <iostream>
# include <algorithm>

using namespace std;
int main()
{

    int n,l;
    cin >> n >> l;
    int*a=new int[n];
     int*b=new int[n];
    for (int i=0;i<n;i++)
    {
        cin >> a[i];
        b[i]=a[i];
    }
    sort(a,a+n);
    int k=-1;

    for (int i=0;i<n;i++)
    {

        if (a[i]>=l)
        {
                    k=i;
                    break;
        }
    }
    if (k==-1)
    {
              cout << "0";
              return 0;
    }
    int s=0;
    int otvet=0;
    int p=a[n-1];
    for (int j=l;j<=p;j++)
    {         for (int i=k;i<n;i++)
             {
                 while(a[i]>=j)
                 {
                         s++;
                         a[i]-=j;
                 }
             }
             otvet=max(otvet,s*j);
                 for (int u=0;u<n;u++)
                 a[u]=b[u];
                 s=0;
    }
    cout << otvet;
    return 0;
}


# include <iostream>
# include <algorithm>

using namespace std;
int main()
{
      //  ifstream fin("input.txt");
//    ofstream fout("output.txt");
    int n,l;
    cin >> n >> l;
    int*a=new int[n];
    for (int i=0;i<n;i++)
    cin >> a[i];
    sort(a,a+n);
    int k=-1;
    for (int i=0;i<n;i++)
    {
        if (a[i]>=l)
        {
                    k=i;
                    break;
        }
    }
    if (k==-1)
    {
              cout << "0";
              return 0;
    }
    int s=1;
    for (int i=k+1;i<n;i++)
    {
        while(a[i]>=a[k])
        {
                         s++;
                         a[i]-=a[k];
        }

    }
    cout << s*a[k];
    return 0;
}


# include <iostream>
# include <algorithm>

using namespace std;
int main()
{
      //  ifstream fin("input.txt");
//    ofstream fout("output.txt");
    int n,l;
    cin >> n >> l;
    int*a=new int[n];
    for (int i=0;i<n;i++)
    cin >> a[i];
    sort(a,a+n);
    int k=-1;
    for (int i=0;i<n;i++)
    {
        if (a[i]>=l)
        {
                    k=i;
                    break;
        }
    }
    if (k==-1)
    {
              cout << "0";
              return 0;
    }
    int s=0;
    for (int i=k;i<n;i++)
    {
        while (a[i]>=l)
        {
              s++;
              a[i]-=l;
        }
    }
    cout << s*l;
    return 0;
}


# include <iostream>
# include <algorithm>

using namespace std;
int main()
{
    int n,l;
    cin >> n >> l;
    int*a=new int[n];
    for (int i=0;i<n;i++)
    {
        cin >> a[i];
    }
    sort(a,a+n);
    int s=0;
    int otvet=0;
    int p=a[n-1];
    for (int j=l;j<=p;j++)
    {
            for (int i=0;i<n;i++)
             {

                         s+=a[i]/j;;
             }
             otvet=max(otvet,s*j);
             s=0;
    }
    cout << otvet;
    return 0;
}


#include <cstdlib>
#include <iostream>

using namespace std;

int main()
{
    int n,l,d[101]={},s=0,h=0;
    cin>>n>>l;
    for (int i=0;i<n;i++)
    cin>>d[i];

    for(int i=0;i<n;i++)
    s+=d[i]/l;

   cout<<s*l;
  //  system("PAUSE");
    return 0;
}


#include <cstdlib>
#include <iostream>

using namespace std;

int main()
{
    int n,l,d[101]={},s=0,h=0,max=-1,max1=-1;
    cin>>n>>l;
    for (int i=0;i=<n;i++)
    cin>>d[i];

      for (int i=0;i<=n;i++)
      if(max1<d[i]) max1=d[i];

    for(int j=0;j<max1-l;j++){
            s=0;
    for(int i=0;i<n;i++){
            h=l+j;
    s+=d[i]/(h);}
    if(max<(s*(l+j)))max=s*(l+j);}
   if(max==-1) cout<<"0"; else
   cout<<max;
   // system("PAUSE");
    return 0;
}


#include <cstdlib>
#include <iostream>

using namespace std;

int main()
{
    int n,l,d[101]={},s=0,h=0,max=-1,max1=-1;
    cin>>n>>l;
    for (int i=0;i<n;i++)
    cin>>d[i];

      for (int i=0;i<=n;i++)
      if(max1<d[i]) max1=d[i];

    for(int j=0;j<max1-l;j++){
            s=0;
    for(int i=0;i<n;i++){
            h=l+j;
    s+=d[i]/(h);}
    if(max<(s*(l+j)))max=s*(l+j);}
   if(max==-1) cout<<"0"; else
   cout<<max;
   // system("PAUSE");
    return 0;
}


#include <cstdlib>
#include <iostream>

using namespace std;

int main()
{
    int n,l,d[101]={},s=0,h=0,max=-1,max1=-1;
    cin>>n>>l;
    for (int i=0;i<n;i++)
    cin>>d[i];

      for (int i=0;i<n;i++)
      if(max1<d[i]) max1=d[i];

    for(int j=0;j<=max1-l;j++){
            s=0;
    for(int i=0;i<n;i++){
            h=l+j;
    s+=d[i]/(h);}
    if(max<(s*(l+j)))max=s*(l+j);}
   if(max==-1) cout<<"0"; else
   cout<<max;
   // system("PAUSE");
    return 0;
}


#include <iostream>
#include <algorithm>
#include <set>
#include <map>
map <int, int > a;
set <int> b;
using namespace std;
int main()
{
    int i,k,l,j,m,n;
    cin >> n >> m;
    k=0;
    for (i=0;i<n;i++){
        cin >> k;
        if (k>=m){
            a[k]++;
            b.insert(k);
        }
    }
    set <int> :: iterator it1,it2,it3;
    int sum,q,w;
    sum=0;
    q=0;
    for (it1=b.begin();it1!=b.end();it1++){
        it2=it1;
        sum=0;
        while (it2!=b.end()){
        sum=sum+(a[*it2]*((*it2)/(*it1)));
        it2++;
        }
//      cout << "sum " << sum << "\n";
        w=*it1*sum;
        q=q>w?q:w;
//      cout << "q " << q << "\n";
    }
    cout << q << "\n";
    return 0;
}


#include <iostream>
#include <algorithm>
#include <set>
#include <map>

using namespace std;
map <int, int > a;
set <int> b;
int main()
{
    int i,k,l,j,m,n;
    cin >> n >> m;
    k=0;
    for (i=0;i<n;i++){
        cin >> k;
        if (k>=m){
            a[k]++;
            b.insert(k);
        }
    }
    set <int> :: iterator it1,it2,it3;
    int sum,q,w;
    sum=0;
    q=0;
    for (it1=b.begin();it1!=b.end();it1++){
        it2=it1;
        sum=0;
        while (it2!=b.end()){
        sum=sum+(a[*it2]*((*it2)/(*it1)));
        it2++;
        }
//      cout << "sum " << sum << "\n";
        w=*it1*sum;
        q=q>w?q:w;
//      cout << "q " << q << "\n";
    }
    cout << q << "\n";
    return 0;
}


#include <iostream>
#include <algorithm>
#include <set>
#include <map>

using namespace std;
map <int, int > a;
set <int> b;
int main()
{
    int i,k,l,j,m,n;
    cin >> n >> m;
    k=0;
    for (i=0;i<n;i++){
        cin >> k;
        if (k>=m){
            a[k]++;
            b.insert(k);
        }
    }
    set <int> :: iterator it1,it2,it3;
    int sum,q,w;
    sum=0;
    q=0;
    if (b.size()==0){
        cout << "0\n";
        return 0;
    }

    it1=b.end();
    it1--;
    j=*it1;
//  cout <<j << "\n";
    for (i=m;i<=j;i++){
        it2=b.begin();
//      it2=b.begin();

        sum=0;
        while (it2!=b.end()){
        sum=sum+(a[*it2]*((*it2)/i));
//      cout << *it2 << " " << a[*it2] << "\n";
        it2++;
        }
//      cout << "sum " << sum << "\n";
        w=(i)*(sum);
        q=q>w?q:w;
//      cout << "q " << q << "\n";
    }
    cout << q << "\n";
    return 0;
}


#include <iostream>
#include <algorithm>
#include <set>
#include <map>

using namespace std;
map <int, int > a;
set <int> b;
int main()
{
    int i,k,l,j,m,n;
    cin >> n >> m;
    k=0;
    for (i=0;i<n;i++){
        cin >> k;
        if (k>=m){
            a[k]++;
            b.insert(k);
        }
    }
    set <int> :: iterator it1,it2,it3;
    int sum,q,w;
    sum=0;
    q=0;

    it1=b.end();
    it1--;
    j=*it1;
//  cout <<j << "\n";
    for (i=m;i<=j;i++){
        it2=b.begin();
//      it2=b.begin();

        sum=0;
        while (it2!=b.end()){
        sum=sum+(a[*it2]*((*it2)/i));
//      cout << *it2 << " " << a[*it2] << "\n";
        it2++;
        }
//      cout << "sum " << sum << "\n";
        w=(i)*(sum);
        q=q>w?q:w;
//      cout << "q " << q << "\n";
    }
    cout << q << "\n";
    return 0;
}


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

#define int long long
const int SIZE = 2e5 + 50;
const int inf = 2139062143;

inline int read()
{
	int x = 0,f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9')
	{
		if (ch == '-') f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9')
	{
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	}
	return f * x;
}

int n,top,now;
int ans[SIZE];
char str[150];
std::stack <int> stc;
struct node
{
	int opt,val;
};
node input[SIZE];

signed main()
{
	n = read();
	while(!stc.empty()) stc.pop();
	for (int i = 1; i <= n << 1; ++i)
	{
		scanf("%s",str);
		if (str[0] == '+') input[i].opt = 1;
		else
		{
			input[i].val = read();
			input[i].opt = 2;
		}
	}
	n <<= 1;
	for (int i = 1; i <= n; ++i)
	{
		if (input[i].opt == 1) top++;
		else if (!top)
		{
			printf("NO\n");
			return 0;
		}
		else top--;
	}
	now = n >> 1;
	for (int i = n; i ; --i)
	{
		if (input[i].opt == 1)
		{
		 	ans[now--] = stc.top();
		 	stc.pop();
		}
		else if (!stc.empty() && input[i].val > stc.top())
		{
		 	printf("NO\n");
		 	return 0;
		}
		else stc.push(input[i].val);
	}
	while (!stc.empty()) stc.pop();
	printf("YES\n");
	for (int i = 1; i <= n >> 1; ++i)
	{
		printf("%lld ",ans[i]);
	}
	return 0;
}


#include<bits/stdc++.h>

#define ri register int

#define inf 0x3f3f3f3f

using std::cin;

const int MAXN=2e5+10;

int n,is_for_sth_impott;
int a[MAXN],pre[MAXN];
int s[MAXN],top;
bool vis[MAXN];

int main()
{
	scanf("%d",&n);
	char op;
	for(ri i=1;i<=n*2;++i)
	{
		cin>>op;
		if(op=='+')vis[i]=1;
		else scanf("%d",&a[i]);
	}

	a[0]=inf;
	s[++top]=0;
	for(ri i=1;i<=n*2;++i)if(!vis[i])
	{
		while(a[i]>a[s[top]])--top;
		pre[i]=s[top];
		s[++top]=i;
	}

	top=0;
	for(ri i=1;i<=n*2;++i)
	{
		if(vis[i])s[++top]=i;
		else
		{
			if(!top || s[top]<pre[i]){printf("NO");return 0;}
			else a[s[top--]]=a[i];
		}
	}

	printf("YES\n");
	for(ri i=1;i<=n*2;++i)if(vis[i])printf("%d ",a[i]);

	return 0;
}


#include <bits/stdc++.h>
#define int long long
#define YES cout<<"YES\n";return;
#define NO cout<<"NO\n";return;
#define write(a) cout<<a<<"\n";return;
using namespace std;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count()); //uid<int> u1(5, 10); u1(rnd);
    long long powmod(long long a,long long b,long long mod) {
        if (b==0 || a==1)  {if (mod==1) return 0; else return 1; }

        if (b%2==0) { long long k=powmod(a,b/2,mod); return (k*k)%mod; }
        else {long long k=powmod(a,b/2,mod); return ( (k*k) %mod *a)% mod; }
    }
    long long gcd(long long a, long long b) {
        if (a==0) return b;
        if (b==0) return a;
        if (a>b) return gcd(a%b,b); else return gcd(b%a,a);
    }
      int prime(int p) { // 1 - простое
        for (int i=2;i*i<=p;i++) {
            if (p%i==0 && i<p) return i;
        }
        return 1;
    }

     int inv(int a, int mod) {
        return powmod(a,mod-2,mod);
    }

  int random_modul() {

    uniform_int_distribution <int> u1(1e9, 2e9);
    int pepega=u1(rnd);
    while (prime(pepega)!=1) pepega=u1(rnd);
    return pepega;
}

    void solve () {

         /* --------- */
         int q;
         cin>>q;
         int ans[q+1];
         for (int i=0;i<=q;i++) ans[i]=0;
         int s=0;
         vector <int> cur;
         for (int i=0;i<2*q;i++) {
             char c; cin>>c;
             if (c=='+') {
                 cur.push_back(s); s++;
             } else {
                 if (cur.empty()) {
                     NO
                 }
                 int k; cin>>k;
                 int mem=cur.back(); cur.pop_back();
                 if (k<ans[mem+1]) {NO}
                 ans[mem]=k;
             }
         }
         cout<<"YES\n";
         for (int i=0;i<q;i++) cout<<ans[i]<<" ";

         /* --------- */
            return;
    }

    signed main() {
       ios_base::sync_with_stdio(0);
       cin.tie(0);
       cout.tie(0);

         // cout<<fixed<<setprecision(10);

          int tututu;
          tututu=1;

         //cin>>tututu; // если нет запросов, то закоментить

          for (int qwerty=0;qwerty<tututu;qwerty++) solve();

        return 0;
    }


#include <bits/stdc++.h>
#define FOR(i,s, n) for(int i = s; i < n; i++)
#define pb push_back
#define ll long long
using namespace std;
int readV(vector<int> a){
    for(vector<int>::iterator it=a.begin();it!=a.end();it++)
    cout<<*it<<" ";
    cout<<endl;
    return 0;
};
typedef pair <int, int> pii;

bool cmp(int a1,int a2){
    return a1>a2;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    //int t;
    //cin>>t;
    //while(t--){
    bool flag=true;
    int n,now=0,prc;
    cin>>n;
    int ans[n];
    vector<pii> a;
    string s;
    FOR(i,0,2*n){
        pii point;
        cin>>s;
        if (s=="+"){
            point.first=0;
            point.second=now;
            now+=1;
            a.pb(point);
        }
        if (s=="-"){
            cin>>prc;
            if (a.empty()){
                flag = false;
                break;
            }
            point = a.back();
            //cout<<point.first<<point.second<<endl;
            if (point.first>prc){
                flag = false;
                break;
            }
            a.pop_back();
            ans [point.second]=prc;
            if (a.empty()) continue;
            point = a.back();
            point.first = max(prc,point.first);
            a.pop_back();
            a.push_back(point);
        }
    }
    if (!a.empty()) flag = false;
    if (flag){
        cout<<"YES"<<endl;
        FOR(i,0,n){cout<<ans[i]<<" ";}
        cout<<endl;
    }
    else{
        cout<<"NO"<<endl;
    }
    //}
    return 0;
}


#include<cstdio>
#include<set>
std::set<int> s;
int st[100005],a[200005],res[100005],pos[200005];
inline int read() {
    register int x=0,f=1;register char s=getchar();
    while(s>'9'||s<'0') {if(s=='-') f=-1;s=getchar();}
    while(s>='0'&&s<='9') {x=x*10+s-'0';s=getchar();}
    return x*f;
}
int main() {
    int n=read(),cur=0,top=0;
    for(register int i=1;i<=2*n;++i) {
        char op=getchar();
        while(op!='+'&&op!='-') op=getchar();
        if(op=='+') {
            s.insert(i); pos[i]=++cur;
        }
        else {
            if(!s.size()) {printf("NO\n");return 0;}
            a[i]=read();
            while(top>0&&a[st[top]]<a[i]) {--top;}
            std::set<int>::iterator it=s.upper_bound(st[top]);
            if(it==s.end()) {printf("NO\n");return 0;}
            res[pos[*it]]=a[i];
            s.erase(it);
            st[++top]=i;
        }
    }
    printf("YES\n");
    for(register int i=1;i<=n;++i) printf("%d ",res[i]);
    return 0;
}


#include<bits/stdc++.h>
#define rep(i,a,b) for (int i = (a); i <= (b); ++i)
#define drep(i,a,b) for (int i = (a); i >= (b); --i)
#define il inline
#define LL long long
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
using namespace std;
il LL read() {
	LL x = 0,y = 1; char ch = getchar(); while (!isdigit(ch)) {if (ch == '-') y = -y; ch = getchar();}
	while (isdigit(ch)) {x = x*10+ch-'0'; ch = getchar();} return x*y;
}
namespace qiqi {
	const int N = 5e5+5; int n,a[N],p[N]; set<int> in,out;
	void main() {
		n = read(); rep(i,1,n*2) {
			char o[10]; scanf("%s",o); if (o[0] == '+') in.insert(i);
			else {int x = read(); a[x] = i; out.insert(i);}
		}
		rep(i,1,n) {
			set<int>::iterator it = in.upper_bound(a[i]); if (it == in.begin()) {puts("NO"); return;}
			int x = *--it; p[x] = i; in.erase(x); out.erase(a[i]); it = out.upper_bound(a[i]);
			if (it == out.begin()) continue; if (*--it > x) {puts("NO"); return;}
		}
		puts("YES"); rep(i,1,n*2) if (p[i]) printf("%d ",p[i]);
	}
}
int main() {
	qiqi::main(); return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;

//for coding
typedef long long ll;
typedef long double ld;
#define all(x) x.begin(), x.end()
#define rd(x) for(auto &i : x) cin >> i;
#define rep(i, l, r) for(int i = (l); i < (r); i++)

//for debug
#define ct(x) for(auto &i : x) cout << i << ' ';

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n;
	cin >> n;
	vector <pair <char, int>> q(2 * n);
	for (int i = 0; i < 2 * n; i++) {
		cin >> q[i].first;
		if (q[i].first == '-')
			cin >> q[i].second;
	}
	vector <pair <vector <int>, int>> vec;
	vector <pair <int, int>> res;
	for (int i = 0; i < 2 * n; i++) {
		if (q[i].first == '+') {
			if (!vec.size() || vec[vec.size() - 1].second != -1)
				vec.push_back({ {}, -1 });
			vec[vec.size() - 1].first.push_back(i);
		}
		else {
			if (vec.size() == 0 || vec[vec.size() - 1].second > q[i].second) {
				cout << "NO";
				return 0;
			}
			res.push_back({ vec[vec.size() - 1].first[vec[vec.size() - 1].first.size() - 1], q[i].second });
			vec[vec.size() - 1].first.pop_back();
			if (!vec[vec.size() - 1].first.size())
				vec.pop_back();
			if(vec.size())
				vec[vec.size() - 1].second = q[i].second;
		}
	}
	cout << "YES\n";
	sort(all(res));
	for (auto i : res) {
		cout << i.second << ' ';
	}
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;

//for coding
typedef long long ll;
typedef long double ld;
#define all(x) x.begin(), x.end()
#define rd(x) for(auto &i : x) cin >> i;
#define rep(i, l, r) for(int i = (l); i < (r); i++)

//for debug
#define ct(x) for(auto &i : x) cout << i << ' ';

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n;
	cin >> n;
	vector <pair <char, int>> q(2 * n);
	for (int i = 0; i < 2 * n; i++) {
		cin >> q[i].first;
		if (q[i].first == '-')
			cin >> q[i].second;
	}
	vector <pair <vector <int>, int>> vec;
	vector <pair <int, int>> res;
	for (int i = 0; i < 2 * n; i++) {
		if (q[i].first == '+') {
			if (!vec.size() || vec[vec.size() - 1].second != -1)
				vec.push_back({ {}, -1 });
			vec[vec.size() - 1].first.push_back(i);
		}
		else {
			if (vec.size() == 0 || vec[vec.size() - 1].second > q[i].second) {
				cout << "NO";
				return 0;
			}
			res.push_back({ vec[vec.size() - 1].first[vec[vec.size() - 1].first.size() - 1], q[i].second });
			vec[vec.size() - 1].first.pop_back();
			if (vec[vec.size() - 1].first.size())
				vec[vec.size() - 1].second = q[i].second;
			if (!vec[vec.size() - 1].first.size())
				vec.pop_back();
		}
	}
	cout << "YES\n";
	sort(all(res));
	for (auto i : res) {
		cout << i.second << ' ';
	}
}


#include<bits/stdc++.h>
#define ll long long
#define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define DEBUG cout<<",here\n";
using namespace std;

struct A
{
    int v,time;
};

int n;
vectorb;
stacka;
A ans[200005];

int cmp(const A&aa,const A&bb){return aa.time<bb.time;}

int main()
{
    cin>>n;
    int prev=0,pret=0;
    int jug=0;
    for(int i=1;i<=2*n;i++){
        char op;cin>>op;
        if(op=='+'){
            a.push({0,i});
        }
        else{
            int x;cin>>x;
            A y;
            if(!a.empty()){
                y=a.top();a.pop();
            }
            else jug=1;
            if(x<y.v){jug=1;}
            ans[x].v=x;ans[x].time=y.time;
            if(!a.empty()){y=a.top();a.pop();}
            a.push({max(x,y.v),y.time});
        }
    }
    if(jug==0){
        cout<<"YES\n";
        sort(ans+1,ans+1+n,cmp);
        for(int i=1;i<=n;i++){cout<<ans[i].v<<" ";}
        cout<<"\n\n";
    }
    else{cout<<"NO\n\n";}

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
int n;
char c[200010];
int a[200010];
int b[200010];
int now;
priority_queue<int,vector<int>, greater<int> >q;
stack<int> st;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=2*n;i++)
	{
		scanf(" %c",&c[i]);
		if(c[i]=='-')
		{
			scanf("%d",&a[i]);
		}
	}
	for(int i=2*n;i>=1;i--)
	{
		if(c[i]=='-')
		{
			q.push(a[i]);
			st.push(a[i]);
		}
		else
		{
			if(q.empty())
			{
				printf("NO");
				return 0;
			}
			if(st.top()!=q.top())
			{
				printf("NO");
				return 0;
			}
			b[++now]=st.top();
			st.pop();
			q.pop();
		}
	}
	printf("YES\n");
	for(int i=now;i>=1;i--)
	{
		printf("%d ",b[i]);
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
int n,nx[200005],id[200005],ls,x,nex[200005];
char s[200005][5];
struct node{
	int l,r,x;
}f[200005<<2];
void build(int x,int l,int r)
{
	f[x].l=l;f[x].r=r;f[x].x=-1e9;
	if(l==r)return;
	int mid=l+r>>1;
	build(x<<1,l,mid);build(x<<1|1,mid+1,r);
}
void ch(int x,int p,int k)
{
	if(f[x].l==f[x].r)
	{
		f[x].x=k;
		return;
	}
	if(f[x<<1].r>=p)ch(x<<1,p,k);
	else ch(x<<1|1,p,k);
	f[x].x=max(f[x<<1].x,f[x<<1|1].x);
}
int qu(int x,int l,int r)
{
	if(l>f[x].r||r<f[x].l)return -1e9;
	if(l<=f[x].l&&f[x].r<=r)return f[x].x;
	return max(qu(x<<1,l,r),qu(x<<1|1,l,r));
}
signed main()
{
	cin>>n;
	build(1,1,n*2);
	for(int i=1;i<=n*2;i++)
	{
		cin>>s[i];
		if(s[i][0]=='-')
		{
			cin>>x;
			if(!ls)puts("NO"),exit(0);
			if(qu(1,ls,i-1)>x)puts("NO"),exit(0);
			ch(1,ls,x);
			id[ls]=x;
			ls=nex[ls];
		}
		else
		{
			nex[i]=ls;ls=i;
		}
	}
	puts("YES");
	for(int i=1;i<=n*2;i++)if(s[i][0]=='+')printf("%d ",id[i]);
}


#include <bits/stdc++.h>
#define N 100005
#define int long long
using namespace std;

template <typename T>

void read(T &a)
{
	T x = 0,f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9')
	{
		if (ch == '-') f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9')
	{
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	}
	a = x * f;
}

template <typename T,typename... Args> void read(T &t,Args &... args) {read(t); read(args...); }

int n,cnt = 0,vis[N],a[N],t[N];
std::vector<int> v;

signed main()
{
	read(n);
	v.push_back(0);
	for (int i = 1; i <= (n << 1); i++)
	{
		char c = getchar();
		while (c != '-' && c != '+') c = getchar();
		if (c == '+')
		{
			v.push_back(++cnt);
			continue;
		}
		int x;
		read(x);
		if (v.size() <= 1 || vis[x]) return puts("NO") * 0;
		if (a[v.back()] > x) return puts("NO") * 0;
		vis[x] = 1;
		a[v.back()] = x;
		a[v[v.size() - 2]] = max(a[v[v.size() - 2]],a[v.back()]);
		v.pop_back();
	}
	puts("YES");
	for (int i = 1; i <= n; i++) t[a[i]]++;
	for (int i = n; i > 0; i--)
	{
		t[i] += t[i + 1];
		if (t[i] > n - i + 1) return puts("NO") * 0;
	}
	for (int i = 1; i <= n; i++)
		printf("%lld ",a[i]);
	puts("");
	return 0;
}


//D
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
set<int>s,un;
const int maxn = 2e5+10;
int ans[maxn];
struct OPT{
	string opt;
	int x;
	OPT(string opt = "",int x = 0):opt(opt),x(x){}
}query[maxn];
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n;
	cin >> n;
	bool ok = 1;
	for(int i = 1;i <= 2*n;i++){
		string opt;
		int x = 0;
		cin >> opt;
		if(opt == "-")cin >> x;
		query[i] = OPT(opt,x);
	}
	int idx = n;
	for(int i = 2*n;i >= 1;i--){
		if(query[i].opt == "-"){
			s.insert(query[i].x);
		}
		else{
			if(!s.size()){
				cout << "NO";
				exit(0);
			}
			int d = (*s.begin());
			ans[idx--] = d;
			s.erase(d);
		}
	}
	idx = 1;
	s.clear();
	for(int i = 1;i <= 2*n;i++){
		if(query[i].opt == "+")s.insert(ans[idx++]);
		else{
			if(!s.size()){
				cout << "NO";
				exit(0);
			}
			if((*s.begin()) != query[i].x)ok = 0;
			s.erase(s.begin());
		}
	}
	if(!ok)cout << "NO";
	else{
		cout << "YES\n";
		for(int i = 1;i <= n;i++)cout << ans[i] << " ";
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;
const int maxn = 1e5 + 5;
int mn[maxn << 2];

void up(int id, int l, int r, int w, int v) {
    if (l == r) {
        mn[id] = v;
        return;
    }
    int mid = (l + r) >> 1;
    if (w <= mid) up(id << 1, l, mid, w, v);
    else up(id << 1 | 1, mid + 1, r, w, v);
    mn[id] = min(mn[id << 1], mn[id << 1 | 1]);
}

int Q(int id, int l, int r, int tl, int tr) {
    if (tl == l && tr == r) {
        return mn[id];
    }
    int mid = (l + r) >> 1;
    if (tr <= mid) return Q(id << 1, l, mid, tl, tr);
    else if (tl > mid) return Q(id << 1 | 1, mid + 1, r, tl, tr);
    return min(Q(id << 1, l, mid, tl, mid), Q(id << 1 | 1, mid + 1, r, mid + 1, tr));
}

char shit[40];
int ids[maxn];

void dfs(int id, int l, int r) {
    if (l == r) {
        printf("%d ", mn[id]);
        return;
    }
    int mid = (l + r) >> 1;
    dfs(id << 1, l, mid);
    dfs(id << 1 | 1, mid + 1, r);
}

int main() {
    int n;
    scanf("%d", &n);
    int add = 1;
    int has = 0;
    memset(mn, 127, sizeof(mn));
    for (int i = 1; i <= n * 2; i++) {
        scanf("%s", shit);
        if (shit[0] == '+') {
            ids[has++] = add;
            add++;
        } else {
            if (has == 0) {
                printf("NO1\n");
                return 0;
            }
            int val;
            scanf("%d", &val);
            int tmp = Q(1, 1, n, ids[has - 1], add - 1);
            if (tmp > val && tmp <= n) {
                printf("NO\n");
                return 0;
            }
            up(1, 1, n, ids[has - 1], val);
            has--;
        }
    }
    printf("%YES\n");
    dfs(1, 1, n);
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
const int maxn = 1e5 + 5;
int mn[maxn << 2];

void up(int id, int l, int r, int w, int v) {
    if (l == r) {
        mn[id] = v;
        return;
    }
    int mid = (l + r) >> 1;
    if (w <= mid) up(id << 1, l, mid, w, v);
    else up(id << 1 | 1, mid + 1, r, w, v);
    mn[id] = max(mn[id << 1], mn[id << 1 | 1]);
}

int Q(int id, int l, int r, int tl, int tr) {
    if (tl == l && tr == r) {
        return mn[id];
    }
    int mid = (l + r) >> 1;
    if (tr <= mid) return Q(id << 1, l, mid, tl, tr);
    else if (tl > mid) return Q(id << 1 | 1, mid + 1, r, tl, tr);
    return max(Q(id << 1, l, mid, tl, mid), Q(id << 1 | 1, mid + 1, r, mid + 1, tr));
}

char shit[40];
int ids[maxn];

void dfs(int id, int l, int r) {
    if (l == r) {
        printf("%d ", mn[id]);
        return;
    }
    int mid = (l + r) >> 1;
    dfs(id << 1, l, mid);
    dfs(id << 1 | 1, mid + 1, r);
}

int main() {
    int n;
    scanf("%d", &n);
    int add = 1;
    int has = 0;
    memset(mn, -1, sizeof(mn));
    for (int i = 1; i <= n * 2; i++) {
        scanf("%s", shit);
        if (shit[0] == '+') {
            ids[has++] = add;
            add++;
        } else {
            if (has == 0) {
                printf("NO\n");
                return 0;
            }
            int val;
            scanf("%d", &val);
            int tmp = Q(1, 1, n, ids[has - 1], add - 1);
//            printf("val %d %d\n", val, tmp);
            if (tmp > val && tmp <= n) {
                printf("NO\n");
                return 0;
            }
            up(1, 1, n, ids[has - 1], val);
            has--;
        }
    }
    printf("%YES\n");
    dfs(1, 1, n);
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
const int maxn = 1e5 + 5;
int mn[maxn << 2];

void up(int id, int l, int r, int w, int v) {
    if (l == r) {
        mn[id] = v;
        return;
    }
    int mid = (l + r) >> 1;
    if (w <= mid) up(id << 1, l, mid, w, v);
    else up(id << 1 | 1, mid + 1, r, w, v);
    mn[id] = min(mn[id << 1], mn[id << 1 | 1]);
}

int Q(int id, int l, int r, int tl, int tr) {
    if (tl == l && tr == r) {
        return mn[id];
    }
    int mid = (l + r) >> 1;
    if (tr <= mid) return Q(id << 1, l, mid, tl, tr);
    else if (tl > mid) return Q(id << 1 | 1, mid + 1, r, tl, tr);
    return min(Q(id << 1, l, mid, tl, mid), Q(id << 1 | 1, mid + 1, r, mid + 1, tr));
}

char shit[40];
int ids[maxn];

void dfs(int id, int l, int r) {
    if (l == r) {
        printf("%d ", mn[id]);
        return;
    }
    int mid = (l + r) >> 1;
    dfs(id << 1, l, mid);
    dfs(id << 1 | 1, mid + 1, r);
}

int main() {
    int n;
    scanf("%d", &n);
    int add = 1;
    int has = 0;
    memset(mn, 127, sizeof(mn));
    for (int i = 1; i <= n * 2; i++) {
        scanf("%s", shit);
        if (shit[0] == '+') {
            ids[has++] = add;
            add++;
        } else {
            if (has == 0) {
                printf("NO\n");
                return 0;
            }
            int val;
            scanf("%d", &val);
            int tmp = Q(1, 1, n, ids[has - 1], add - 1);
            if (tmp > val && tmp <= n) {
                printf("NO\n");
                return 0;
            }
            up(1, 1, n, ids[has - 1], val);
            has--;
        }
    }
    printf("%YES\n");
    dfs(1, 1, n);
    return 0;
}


//package start;

import java.io.*;
import java.lang.*;
import java.util.*;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

public class Main extends IO{

    public static void main(String[] args) throws Exception{
        int count = readInt();
        for (int i = 0; i < count; i++) {
            int[] size = readArrayInt(" ");
            HashMap<Integer, int[]> lastLeftToRight = new HashMap<>();
            for (int index = 0; index < size[0]; index++){
                int[] arr = readArrayInt(" ");
                lastLeftToRight.put(arr[size[1] - 1], arr);
            }
            HashMap<Integer, int[]> lastTopToRight = new HashMap<>();
            for (int index = 0; index < size[1]; index++) {
                int[] arr = readArrayInt(" ");
                lastTopToRight.put(arr[size[0] - 1], arr);
            }
            Set<Integer> keyLastArr =  new HashSet<>(lastLeftToRight.keySet());
            keyLastArr.retainAll(lastTopToRight.keySet());
            int[] lastArr = lastTopToRight.get(keyLastArr.iterator().next());
            for (int value : lastArr){
                writeArray(lastLeftToRight.get(value), " ", true);
            }
        }
        print();

    }
}

class math {

    protected static long remains = 0x3B9ACA07; // 1000000007

    protected static int gcd(int a, int b) { // NOD
        if (b == 0) {
            return a;
        }
        return gcd(b, a % b);
    }

    protected static long gcd(long a, long b) {
        if (b == 0) {
            return a;
        }
        return gcd(b, a % b);
    }

    protected static float gcd(float a, float b) {
        if (b == 0) {
            return a;
        }
        return gcd(b, a % b);
    }

    protected static double gcd(double a, double b) {
        if (b == 0) {
            return a;
        }
        return gcd(b, a % b);
    }

    protected static double lcm(double a, double b) { // NOK
        return a / gcd(a, b) * b;
    }

    protected static float lcm(float a, float b) { // NOK
        return a / gcd(a, b) * b;
    }

    protected static int lcm(int a, int b) { // NOK
        return a / gcd(a, b) * b;
    }

    protected static long lcm(long a, long b) {
        return a / gcd(a, b) * b;

    }

    protected static double log(double value, int base) {
        return Math.log(value) / Math.log(base);
    }

    protected static long factorial(int number) {
        if (number < 0) {
            return 0;
        }
        return solveFactorial(number);
    }

    private static long solveFactorial(int number) {
        if (number > 0) {
            return solveFactorial(number - 1) * number;
        }
        return 1;
    }

}

class Int implements Comparable<Integer> {

    protected int value;

    Int(int value) {
        this.value = value;
    }

    public Int add(int value) {
        this.value += value;
        return this;
    }

    @Override
    public int compareTo(Integer o) {
        return (this.value < o) ? -1 : ((this.value == o) ? 0 : 1);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == (Integer) obj;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return value;
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
    }
}

class Fraction<T extends Number> extends Pair {

    private Fraction(T dividend, T divider) {
        super(dividend, divider);
        reduce();
    }

    protected static <T extends Number> Fraction<T> createFraction(T dividend, T divider) {
        return new Fraction<>(dividend, divider);
    }

    protected void reduce() {
        if (getFirstElement() instanceof Integer) {
            Integer Dividend = (Integer) getFirstElement();
            Integer Divider = (Integer) getSecondElement();
            int gcd = math.gcd(Dividend, Divider);
            setFirst(Dividend / gcd);
            setSecond(Divider / gcd);
        } else if (getFirstElement() instanceof Long) {
            Long Dividend = (Long) getFirstElement();
            Long Divider = (Long) getSecondElement();
            long gcd = math.gcd(Dividend, Divider);
            setFirst(Dividend / gcd);
            setSecond(Divider / gcd);
        } else if (getFirstElement() instanceof Float) {
            Float Dividend = (Float) getFirstElement();
            Float Divider = (Float) getSecondElement();
            float gcd = math.gcd(Dividend, Divider);
            setFirst(Dividend / gcd);
            setSecond(Divider / gcd);
        } else if (getFirstElement() instanceof Double) {
            Double Dividend = (Double) getFirstElement();
            Double Divider = (Double) getSecondElement();
            double gcd = math.gcd(Dividend, Divider);
            setFirst(Dividend / gcd);
            setSecond(Divider / gcd);
        }
    }

    protected void addWithoutReturn(Fraction number) throws UnsupportedOperationException {
        add(number, 0);
    }

    private Fraction add(Fraction number, int function) throws UnsupportedOperationException {
        if (getFirstElement() instanceof Integer && number.getFirstElement() instanceof Integer) {
            Integer Dividend = (Integer) getFirstElement();
            Integer Divider = (Integer) getSecondElement();
            Integer Dividend1 = (Integer) number.getFirstElement();
            Integer Divider1 = (Integer) number.getSecondElement();
            Integer lcm = math.lcm(Divider, Divider1);
            if (function == 0) {
                setFirst((lcm / Divider) * Dividend + (lcm / Divider1) * Dividend1);
                setSecond(lcm);
                reduce();
                return null;
            }
            Fraction result = Fraction.createFraction((lcm / Divider) * Dividend + (lcm / Divider1) * Dividend1, lcm);
            result.reduce();
            return result;

        } else if (getFirstElement() instanceof Long && number.getFirstElement() instanceof Long) {
            Long Dividend = (Long) getFirstElement();
            Long Divider = (Long) getSecondElement();
            Long Dividend1 = (Long) number.getFirstElement();
            Long Divider1 = (Long) number.getSecondElement();
            Long lcm = math.lcm(Divider, Divider1);
            if (function == 0) {
                setFirst((lcm / Divider) * Dividend + (lcm / Divider1) * Dividend1);
                setSecond(lcm);
                reduce();
                return null;
            }
            Fraction result = Fraction.createFraction((lcm / Divider) * Dividend + (lcm / Divider1) * Dividend1, lcm);
            result.reduce();
            return result;
        } else if (getFirstElement() instanceof Float && number.getFirstElement() instanceof Float) {
            Float Dividend = (Float) getFirstElement();
            Float Divider = (Float) getSecondElement();
            Float Dividend1 = (Float) number.getFirstElement();
            Float Divider1 = (Float) number.getSecondElement();
            Float lcm = math.lcm(Divider, Divider1);
            if (function == 0) {
                setFirst((lcm / Divider) * Dividend + (lcm / Divider1) * Dividend1);
                setSecond(lcm);
                reduce();
                return null;
            }
            Fraction result = Fraction.createFraction((lcm / Divider) * Dividend + (lcm / Divider1) * Dividend1, lcm);
            result.reduce();
            return result;
        } else if (getFirstElement() instanceof Double && number.getFirstElement() instanceof Double) {
            Double Dividend = (Double) getFirstElement();
            Double Divider = (Double) getSecondElement();
            Double Dividend1 = (Double) number.getFirstElement();
            Double Divider1 = (Double) number.getSecondElement();
            Double lcm = math.lcm(Divider, Divider1);
            if (function == 0) {
                setFirst((lcm / Divider) * Dividend + (lcm / Divider1) * Dividend1);
                setSecond(lcm);
                reduce();
                return null;
            }
            Fraction result = Fraction.createFraction((lcm / Divider) * Dividend + (lcm / Divider1) * Dividend1, lcm);
            result.reduce();
            return result;
        } else {
            throw new UnsupportedOperationException();
        }
    }

    protected Fraction addWithReturn(Fraction number) {
        return add(number, 1);
    }

    protected void multiplyWithoutReturn(Fraction number) throws UnsupportedOperationException {
        multiply(number, 0);
    }

    protected Fraction multiplyWithReturn(Fraction number) throws UnsupportedOperationException {
        return multiply(number, 1);
    }

    private Fraction multiply(Fraction number, int function) throws UnsupportedOperationException {
        if (getFirstElement() instanceof Integer && number.getFirstElement() instanceof Integer) {
            Integer first = (Integer) getFirstElement() * (Integer) number.getFirstElement();
            Integer second = (Integer) getSecondElement() * (Integer) number.getSecondElement();
            if (function == 0) {
                setFirst(first);
                setSecond(second);
                reduce();
                return null;
            }
            Fraction answer = Fraction.createFraction(first, second);
            answer.reduce();
            return answer;
        } else if (getFirstElement() instanceof Long && number.getFirstElement() instanceof Long) {
            Long first = (Long) getFirstElement() * (Long) number.getFirstElement();
            Long second = (Long) getSecondElement() * (Long) number.getSecondElement();
            if (function == 0) {
                setFirst(first);
                setSecond(second);
                reduce();
                return null;
            }
            Fraction answer = Fraction.createFraction(first, second);
            answer.reduce();
            return answer;

        } else if (getFirstElement() instanceof Float && number.getFirstElement() instanceof Float) {
            Float first = (Float) getFirstElement() * (Float) number.getFirstElement();
            Float second = (Float) getSecondElement() * (Float) number.getSecondElement();
            if (function == 0) {
                setFirst(first);
                setSecond(second);
                reduce();
                return null;
            }
            Fraction answer = Fraction.createFraction(first, second);
            answer.reduce();
            return answer;
        } else if (getFirstElement() instanceof Double && number.getFirstElement() instanceof Double) {
            Double first = (Double) getFirstElement() * (Double) number.getFirstElement();
            Double second = (Double) getSecondElement() * (Double) number.getSecondElement();
            if (function == 0) {
                setFirst(first);
                setSecond(second);
                reduce();
                return null;
            }
            Fraction answer = Fraction.createFraction(first, second);
            answer.reduce();
            return answer;
        } else {
            throw new UnsupportedOperationException();
        }
    }
}

class Pair<T, T1> implements Cloneable {

    private T first;
    private T1 second;

    Pair(T obj, T1 obj1) {
        first = obj;
        second = obj1;
    }

    protected static <T, T1> Pair<T, T1> createPair(T element, T1 element1) {
        return new Pair<>(element, element1);
    }

    protected T getFirstElement() {
        return first;
    }

    protected T1 getSecondElement() {
        return second;
    }

    protected void setFirst(T element) {
        first = element;
    }

    protected void setSecond(T1 element) {
        second = element;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Pair)) {
            return false;
        }
        Pair pair = (Pair) obj;
        return first.equals(pair.first) && second.equals(pair.second);
    }

    @Override
    public int hashCode() {
        int hashCode = 1;
        hashCode = 31 * hashCode + (first == null ? 0 : first.hashCode());
        return 31 * hashCode + (second == null ? 0 : second.hashCode());
    }

    @Override
    public Object clone() {
        return Pair.createPair(first, second);
    }
}

class Graph {

    private int[][] base;
    private boolean[] used;
    private int quantity;
    private Integer[] ancestor;

    public int[][] getBase() {
        return base;
    }

    public boolean[] getUsed() {
        return used;
    }

    public int getQuantity() {
        return quantity;
    }

    public Integer[] getAncestor() {
        return ancestor;
    }

    public void setBase(int[][] base) {
        this.base = base;
    }

    protected void start(int length) {
        used = new boolean[length];
        ancestor = new Integer[length];
        Arrays.fill(ancestor, -1);
        quantity = 0;
    }

    protected void edgesMatrixToDefault(int length, int inputQuantity, boolean readConsole, int[][] value) throws Exception {
        base = new int[length][];
        List<ArrayList<Integer>> inputBase = new ArrayList<>();
        for (int i = 0; i < length; i++) {
            inputBase.add(new ArrayList<>());
        }
        for (int i = 0; i < inputQuantity; i++) {
            int[] input = readConsole ? IO.readArrayInt(" ") : value[i];
            inputBase.get(input[0] - 1).add(input[1] - 1);
            inputBase.get(input[0] - 1).add(input[2]); // price
            inputBase.get(input[1] - 1).add(input[0] - 1);
            inputBase.get(input[1] - 1).add(input[2]); // price
        }
        for (int i = 0; i < length; i++) {
            base[i] = inputBase.get(i).stream().mapToInt(Integer::intValue).toArray();
        }
        start(length);
    }

    protected void adjacencyMatrixToDefault(int length, int not, boolean readConsole, int[][] value) throws Exception {
        this.base = new int[length][];
        List<Integer> buffer = new ArrayList<>();
        for (int i = 0; i < length; i++) {
            int[] InputArray = readConsole ? IO.readArrayInt(" ") : value[i];
            for (int index = 0; index < length; index++) {
                if (i != index && InputArray[index] != not) {
                    buffer.add(index);
                    // buffer.add(InputArray[index]); // price
                }
            }
            this.base[i] = buffer.stream().mapToInt(Integer::intValue).toArray();
            buffer.clear();
        }
        start(length);
    }

    protected int dfs(int position) throws Exception {
        used[position] = true;
        int next;
        int count = 0;
        for (int index = 0; index < base[position].length; index += 2) {
            next = base[position][index];
            if (!used[next]) {
                ancestor[next] = position;
                count += dfs(next);
            }
             /*else {
                if (next != ancestor[position]) { // if cycle
                    throw new Exception();
                }
            }*/
        }
        if (base[position].length == 2 && base[position][0] == ancestor[position]) {
            return 1;
        }
        return count;
    }

    protected int dijkstra(int start, int stop, int size) {
        start--;
        stop--;
        int[] dist = new int[size];
        for (int i = 0; i < size; i++) {
            if (i != start) {
                dist[i] = Integer.MAX_VALUE;
            }
            ancestor[i] = start;
        }

        Queue<int[]> queue = new PriorityQueue<>(Comparator.comparingInt((int[] ints) -> ints[1]));
        queue.add(new int[]{start, 0});
        int position;
        int[] getQueue;
        while (queue.size() != 0) {
            getQueue = queue.poll();
            position = getQueue[0];
            if (getQueue[1] > dist[position]) {
                continue;
            }
            for (int index = 0; index < this.base[position].length; index += 2) {
                if (dist[position] + this.base[position][index + 1] < dist[this.base[position][index]] && !this.used[this.base[position][index]]) {
                    dist[this.base[position][index]] = dist[position] + this.base[position][index + 1];
                    this.ancestor[this.base[position][index]] = position;
                    queue.add(new int[]{this.base[position][index], dist[this.base[position][index]]});
                }
            }
            used[position] = true;
        }
        return dist[stop] == Integer.MAX_VALUE ? -1 : dist[stop];
    }

    protected static boolean solveFloydWarshall(int[][] base, int length, int not) {
        for (int k = 0; k < length; k++) {
            for (int i = 0; i < length; i++) {
                for (int j = 0; j < length; j++) {
                    if (base[i][k] == not || base[k][j] == not) {
                        continue;
                    }
                    int total = base[i][k] + base[k][j];
                    if (base[i][j] != not) {
                        base[i][j] = Math.min(base[i][j], total);
                    } else {
                        base[i][j] = total;
                    }
                }
            }
        }
        for (int index = 0; index < length; index++) {
            if (base[index][index] != 0) { // if cycle
                return false;
            }
        }
        return true;
    }

    protected static Pair<Long, int[][]> solveKruskal(int[][] edgesMatrix, final int countVertex, final int indexSort) {
        int[][] answer = new int[countVertex - 1][2];
        long sum = 0;
        Arrays.sort(edgesMatrix, Comparator.comparingInt(value -> value[indexSort]));
        SystemOfDisjointSets dsu = new SystemOfDisjointSets(countVertex);
        for (int i = 0; i < countVertex; i++) {
            dsu.makeSet(i);
        }
        int index = 0;
        for (int[] value : edgesMatrix) {
            if (dsu.mergeSets(value[0], value[1])) {
                sum += value[indexSort];
                answer[index] = new int[]{value[0], value[1]};
                index++;
            }
        }
        if (index < countVertex - 1) {
            return Pair.createPair(null, null);
        }
        return Pair.createPair(sum, answer);
    }

    static class SegmentTree {

        private int[] segmentArray;
        private BiFunction<Integer, Integer, Integer> function;

        protected void setSegmentArray(int[] segmentArray) {
            this.segmentArray = segmentArray;
        }

        protected int[] getSegmentArray() {
            return segmentArray.clone();
        }

        protected void setFunction(BiFunction<Integer, Integer, Integer> function) {
            this.function = function;
        }

        protected BiFunction<Integer, Integer, Integer> getFunction() {
            return function;
        }

        SegmentTree() {

        }

        SegmentTree(int[] startBase, int neutral, BiFunction<Integer, Integer, Integer> function) {
            this.function = function;
            int length = startBase.length;
            int[] base;
            if ((length & (length - 1)) != 0) {
                int pow = 0;
                while (length > 0) {
                    length >>= 1;
                    pow++;
                }
                pow--;
                base = new int[2 << pow];
                System.arraycopy(startBase, 0, base, 0, startBase.length);
                Arrays.fill(base, startBase.length, base.length, neutral);

            } else {
                base = startBase;
            }
            segmentArray = new int[base.length << 1]; // maybe * 4
            Arrays.fill(segmentArray, neutral);
            inDepth(base, 1, 0, base.length - 1);
        }

        private void inDepth(int[] base, int position, int low, int high) {
            if (low == high) {
                segmentArray[position] = base[low];
            } else {
                int mid = (low + high) >> 1;
                inDepth(base, position << 1, low, mid);
                inDepth(base, (position << 1) + 1, mid + 1, high);
                segmentArray[position] = function.apply(segmentArray[position << 1], segmentArray[(position << 1) + 1]);
            }
        }

        protected int getValue(int left, int right, int neutral) {
            return findValue(1, 0, ((segmentArray.length) >> 1) - 1, left, right, neutral);
        }

        private int findValue(int position, int low, int high, int left, int right, int neutral) {
            if (left > right) {
                return neutral;
            }
            if (left == low && right == high) {
                return segmentArray[position];
            }
            int mid = (low + high) >> 1;
            return function.apply(findValue(position << 1, low, mid, left, Math.min(right, mid), neutral),
                    findValue((position << 1) + 1, mid + 1, high, Math.max(left, mid + 1), right, neutral));
        }

        protected void replaceValue(int index, int value) {
            update(1, 0, (segmentArray.length >> 1) - 1, index, value);
        }

        private void update(int position, int low, int high, int index, int value) {
            if (low == high) {
                segmentArray[position] = value;
            } else {
                int mid = (low + high) >> 1;
                if (index <= mid) {
                    update(position << 1, low, mid, index, value);
                } else {
                    update((position << 1) + 1, mid + 1, high, index, value);
                }
                segmentArray[position] = function.apply(segmentArray[position << 1], segmentArray[(position << 1) + 1]);
            }
        }
    }

    static class SegmentTreeGeneric<T> {

        private Object[] segmentArray;
        private BiFunction<T, T, T> function;

        protected void setSegmentArray(T[] segmentArray) {
            this.segmentArray = segmentArray;
        }

        protected Object getSegmentArray() {
            return segmentArray.clone();
        }

        protected void setFunction(BiFunction<T, T, T> function) {
            this.function = function;
        }

        protected BiFunction<T, T, T> getFunction() {
            return function;
        }

        SegmentTreeGeneric() {

        }

        SegmentTreeGeneric(T[] startBase, T neutral, BiFunction<T, T, T> function) {
            this.function = function;
            int length = startBase.length;
            Object[] base;
            if ((length & (length - 1)) != 0) {
                int pow = 0;
                while (length > 0) {
                    length >>= 1;
                    pow++;
                }
                pow--;
                base = new Object[2 << pow];
                System.arraycopy(startBase, 0, base, 0, startBase.length);
                Arrays.fill(base, startBase.length, base.length, neutral);

            } else {
                base = startBase;
            }
            segmentArray = new Object[base.length << 1]; // maybe * 4
            Arrays.fill(segmentArray, neutral);
            inDepth(base, 1, 0, base.length - 1);
        }

        private void inDepth(Object[] base, int position, int low, int high) {
            if (low == high) {
                segmentArray[position] = base[low];
            } else {
                int mid = (low + high) >> 1;
                inDepth(base, position << 1, low, mid);
                inDepth(base, (position << 1) + 1, mid + 1, high);
                segmentArray[position] = function.apply((T) segmentArray[position << 1], (T) segmentArray[(position << 1) + 1]);
            }
        }

        protected T getValue(int left, int right, T neutral) {
            return findValue(1, 0, ((segmentArray.length) >> 1) - 1, left, right, neutral);
        }

        private T findValue(int position, int low, int high, int left, int right, T neutral) {
            if (left > right) {
                return neutral;
            }
            if (left == low && right == high) {
                return (T) segmentArray[position];
            }
            int mid = (low + high) >> 1;
            return function.apply(findValue(position << 1, low, mid, left, Math.min(right, mid), neutral),
                    findValue((position << 1) + 1, mid + 1, high, Math.max(left, mid + 1), right, neutral));
        }

        protected void replaceValue(int index, T value) {
            update(1, 0, (segmentArray.length >> 1) - 1, index, value);
        }

        private void update(int position, int low, int high, int index, T value) {
            if (low == high) {
                segmentArray[position] = value;
            } else {
                int mid = (low + high) >> 1;
                if (index <= mid) {
                    update(position << 1, low, mid, index, value);
                } else {
                    update((position << 1) + 1, mid + 1, high, index, value);
                }
                segmentArray[position] = function.apply((T) segmentArray[position << 1], (T) segmentArray[(position << 1) + 1]);
            }
        }
    }
}

class SystemOfDisjointSets {

    private int[] rank;
    private int[] dsu;

    SystemOfDisjointSets(int size) {
        this.rank = new int[size];
        this.dsu = new int[size];
    }

    protected void makeSet(int value) {
        dsu[value] = value;
        rank[value] = 0;
    }

    protected int findSet(int value) {
        if (value == dsu[value]) {
            return value;
        }
        return dsu[value] = findSet(dsu[value]);
    }

    protected boolean mergeSets(int first, int second) {
        first = findSet(first);
        second = findSet(second);
        if (first != second) {
            if (rank[first] < rank[second]) {
                int number = first;
                first = second;
                second = number;
            }
            dsu[second] = first;
            if (rank[first] == rank[second]) {
                rank[first]++;
            }
            return true;
        }
        return false;
    }
}

interface Array {
    void useArray(int[] a);
}

interface Method {
    void use();
}

class FastSort {

    protected static int[] sort(int[] array, int ShellHeapMergeMyInsertionSort) {
        sort(array, ShellHeapMergeMyInsertionSort, array.length);
        return array;
    }

    protected static int[] sortClone(int[] array, int ShellHeapMergeMyInsertionSort) {
        int[] base = array.clone();
        sort(base, ShellHeapMergeMyInsertionSort, array.length);
        return base;
    }

    private static void sort(int[] array, int ShellHeapMergeMyInsertionSort, int length) {
        if (ShellHeapMergeMyInsertionSort < 0 || ShellHeapMergeMyInsertionSort > 4) {
            Random random = new Random();
            ShellHeapMergeMyInsertionSort = random.nextInt(4);
        }
        if (ShellHeapMergeMyInsertionSort == 0) {
            ShellSort(array);
        } else if (ShellHeapMergeMyInsertionSort == 1) {
            HeapSort(array);
        } else if (ShellHeapMergeMyInsertionSort == 2) {
            MergeSort(array, 0, length - 1);
        } else if (ShellHeapMergeMyInsertionSort == 3) {
            straightMergeSort(array, length);
        } else if (ShellHeapMergeMyInsertionSort == 4) {
            insertionSort(array);
        }
    }

    private static void straightMergeSort(int[] array, int size) {
        if (size == 0) {
            return;
        }
        int length = (size >> 1) + ((size % 2) == 0 ? 0 : 1);
        Integer[][] ZeroBuffer = new Integer[length + length % 2][2];
        Integer[][] FirstBuffer = new Integer[0][0];
        for (int index = 0; index < length; index++) {
            int ArrayIndex = index << 1;
            int NextArrayIndex = (index << 1) + 1;
            if (NextArrayIndex < size) {
                if (array[ArrayIndex] > array[NextArrayIndex]) {
                    ZeroBuffer[index][0] = array[NextArrayIndex];
                    ZeroBuffer[index][1] = array[ArrayIndex];
                } else {
                    ZeroBuffer[index][0] = array[ArrayIndex];
                    ZeroBuffer[index][1] = array[NextArrayIndex];
                }
            } else {
                ZeroBuffer[index][0] = array[ArrayIndex];
            }
        }
        boolean position = false;
        int pointer0, pointer, pointer1, number = 4, NewPointer, count;
        Integer[][] NewBuffer;
        Integer[][] OldBuffer;
        length = (size >> 2) + ((size % 4) == 0 ? 0 : 1);
        while (true) {
            pointer0 = 0;
            count = (number >> 1) - 1;
            if (!position) {
                FirstBuffer = new Integer[length + length % 2][number];
                NewBuffer = FirstBuffer;
                OldBuffer = ZeroBuffer;
            } else {
                ZeroBuffer = new Integer[length + length % 2][number];
                NewBuffer = ZeroBuffer;
                OldBuffer = FirstBuffer;
            }
            for (int i = 0; i < length; i++) {
                pointer = 0;
                pointer1 = 0;
                NewPointer = pointer0 + 1;
                if (length == 1) {
                    for (int g = 0; g < size; g++) {
                        if (pointer > count || OldBuffer[pointer0][pointer] == null) {
                            array[g] = OldBuffer[NewPointer][pointer1];
                            pointer1++;
                        } else if (pointer1 > count || OldBuffer[NewPointer][pointer1] == null) {
                            if (OldBuffer[pointer0][pointer] == null) {
                                continue;
                            }
                            array[g] = OldBuffer[pointer0][pointer];
                            pointer++;
                        } else if (OldBuffer[pointer0][pointer] >= OldBuffer[NewPointer][pointer1]) {
                            array[g] = OldBuffer[NewPointer][pointer1];
                            pointer1++;
                        } else {
                            array[g] = OldBuffer[pointer0][pointer];
                            pointer++;
                        }
                    }
                    return;
                }
                for (int g = 0; g < number; g++) {
                    if (pointer > count || OldBuffer[pointer0][pointer] == null) {
                        if (OldBuffer[NewPointer][pointer1] == null) {
                            continue;
                        }
                        NewBuffer[i][g] = OldBuffer[NewPointer][pointer1];
                        pointer1++;
                    } else if (pointer1 > count || OldBuffer[NewPointer][pointer1] == null) {
                        if (OldBuffer[pointer0][pointer] == null) {
                            continue;
                        }
                        NewBuffer[i][g] = OldBuffer[pointer0][pointer];
                        pointer++;
                    } else if (OldBuffer[pointer0][pointer] >= OldBuffer[NewPointer][pointer1]) {
                        NewBuffer[i][g] = OldBuffer[NewPointer][pointer1];
                        pointer1++;
                    } else {
                        NewBuffer[i][g] = OldBuffer[pointer0][pointer];
                        pointer++;
                    }
                }
                pointer0 += 2;
            }
            position = !position;
            length = (length >> 1) + length % 2;
            number <<= 1;
        }
    }

    private static void ShellSort(int[] array) {
        int j;
        for (int gap = (array.length >> 1); gap > 0; gap >>= 1) {
            for (int i = gap; i < array.length; i++) {
                int temp = array[i];
                for (j = i; j >= gap && array[j - gap] > temp; j -= gap) {
                    array[j] = array[j - gap];
                }
                array[j] = temp;
            }
        }
    }

    private static void HeapSort(int[] array) {
        for (int i = (array.length >> 1) - 1; i >= 0; i--)
            shiftDown(array, i, array.length);
        for (int i = array.length - 1; i > 0; i--) {
            swap(array, 0, i);
            shiftDown(array, 0, i);
        }
    }

    private static void shiftDown(int[] array, int i, int n) {
        int child;
        int tmp;
        for (tmp = array[i]; leftChild(i) < n; i = child) {
            child = leftChild(i);
            if (child != n - 1 && (array[child] < array[child + 1]))
                child++;
            if (tmp < array[child])
                array[i] = array[child];
            else
                break;
        }
        array[i] = tmp;
    }

    private static int leftChild(int i) {
        return (i << 1) + 1;
    }

    private static void swap(int[] array, int i, int j) {
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    private static void MergeSort(int[] array, int low, int high) {
        if (low < high) {
            int mid = (low + high) >> 1;
            MergeSort(array, low, mid);
            MergeSort(array, mid + 1, high);
            merge(array, low, mid, high);
        }
    }

    private static void merge(int[] array, int low, int mid, int high) {
        int n = high - low + 1;
        int[] Temp = new int[n];
        int i = low, j = mid + 1;
        int k = 0;
        while (i <= mid || j <= high) {
            if (i > mid)
                Temp[k++] = array[j++];
            else if (j > high)
                Temp[k++] = array[i++];
            else if (array[i] < array[j])
                Temp[k++] = array[i++];
            else
                Temp[k++] = array[j++];
        }
        for (j = 0; j < n; j++)
            array[low + j] = Temp[j];
    }

    private static void insertionSort(int[] elements) {
        for (int i = 1; i < elements.length; i++) {
            int key = elements[i];
            int j = i - 1;
            while (j >= 0 && key < elements[j]) {
                elements[j + 1] = elements[j];
                j--;
            }
            elements[j + 1] = key;
        }
    }
}

class IO {

    private static BufferedReader read;
    private static boolean fileInput = false;
    private static BufferedWriter write;
    private static boolean fileOutput = false;

    public static void setFileInput(boolean fileInput) {
        IO.fileInput = fileInput;
    }

    public static void setFileOutput(boolean fileOutput) {
        IO.fileOutput = fileOutput;
    }

    private static void startInput() {
        try {
            read = new BufferedReader(fileInput ? new FileReader("input.txt") : new InputStreamReader(System.in));
        } catch (Exception error) {
        }
    }

    private static void startOutput() {
        try {
            write = new BufferedWriter(fileOutput ? new FileWriter("output.txt") : new OutputStreamWriter(System.out));
        } catch (Exception error) {
        }
    }

    protected static int readInt() throws Exception {
        if (read == null) {
            startInput();
        }
        return Integer.parseInt(read.readLine());
    }

    protected static long readLong() throws Exception {
        if (read == null) {
            startInput();
        }
        return Long.parseLong(read.readLine());
    }

    protected static String readString() throws Exception {
        if (read == null) {
            startInput();
        }
        return read.readLine();
    }

    protected static int[] readArrayInt(String split) throws Exception {
        if (read == null) {
            startInput();
        }
        return Arrays.stream(read.readLine().split(split)).mapToInt(Integer::parseInt).toArray();
    }

    protected static long[] readArrayLong(String split) throws Exception {
        if (read == null) {
            startInput();
        }
        return Arrays.stream(read.readLine().split(split)).mapToLong(Long::parseLong).toArray();
    }

    protected static String[] readArrayString(String split) throws Exception {
        if (read == null) {
            startInput();
        }
        return read.readLine().split(split);
    }

    protected static void writeArray(int[] array, String split, boolean enter) {
        if (write == null) {
            startOutput();
        }
        try {
            int length = array.length;
            for (int index = 0; index < length; index++) {
                write.write(Integer.toString(array[index]));
                if (index + 1 != length) {
                    write.write(split);
                }
            }
            if (enter) {
                writeEnter();
            }
        } catch (Exception error) {
        }
    }

    protected static void writeArray(Integer[] array, String split, boolean enter) {
        if (write == null) {
            startOutput();
        }
        try {
            int length = array.length;
            for (int index = 0; index < length; index++) {
                write.write(Integer.toString(array[index]));
                if (index + 1 != length) {
                    write.write(split);
                }
            }
            if (enter) {
                writeEnter();
            }
        } catch (Exception error) {
        }
    }

    protected static void writeArray(long[] array, String split, boolean enter) {
        if (write == null) {
            startOutput();
        }
        try {
            int length = array.length;
            for (int index = 0; index < length; index++) {
                write.write(Long.toString(array[index]));
                if (index + 1 != length) {
                    write.write(split);
                }
            }
            if (enter) {
                writeEnter();
            }
        } catch (Exception error) {
        }
    }

    protected static void writeArray(Long[] array, String split, boolean enter) {
        if (write == null) {
            startOutput();
        }
        try {
            int length = array.length;
            for (int index = 0; index < length; index++) {
                write.write(Long.toString(array[index]));
                if (index + 1 != length) {
                    write.write(split);
                }
            }
            if (enter) {
                writeEnter();
            }
        } catch (Exception error) {
        }
    }

    public static void writeArray(String[] array, String split, boolean enter) {
        if (write == null) {
            startOutput();
        }
        try {
            int length = array.length;
            for (int index = 0; index < length; index++) {
                write.write(array[index]);
                if (index + 1 != length) {
                    write.write(split);
                }
            }
            if (enter) {
                writeEnter();
            }
        } catch (Exception ignored) {
        }
    }

    protected static void writeArray(boolean[] array, String split, boolean enter) {
        if (write == null) {
            startOutput();
        }
        try {
            int length = array.length;
            for (int index = 0; index < length; index++) {
                write.write(Boolean.toString(array[index]));
                if (index + 1 != length) {
                    write.write(split);
                }
            }
            if (enter) {
                writeEnter();
            }
        } catch (Exception ignored) {
        }
    }

    protected static void writeInt(int number, String end) {
        if (write == null) {
            startOutput();
        }
        try {
            write.write(Integer.toString(number));
            write.write(end);
        } catch (Exception ignored) {
        }
    }

    protected static void writeInt(Integer number, String end) {
        if (write == null) {
            startOutput();
        }
        try {
            write.write(Integer.toString(number));
            write.write(end);
        } catch (Exception ignored) {
        }
    }

    protected static void writeLong(long number, String end) {
        if (write == null) {
            startOutput();
        }
        try {
            write.write(Long.toString(number));
            write.write(end);
        } catch (Exception ignored) {
        }
    }

    protected static void writeLong(Long number, String end) {
        if (write == null) {
            startOutput();
        }
        try {
            write.write(Long.toString(number));
            write.write(end);
        } catch (Exception ignored) {
        }
    }

    protected static void writeString(String word, String end) {
        if (write == null) {
            startOutput();
        }
        try {
            write.write(word);
            write.write(end);
        } catch (Exception ignored) {
        }
    }

    protected static void writeBoolean(boolean value, String end) {
        if (write == null) {
            startOutput();
        }
        try {
            write.write(value ? "true" : "false");
            write.write(end);
        } catch (Exception ignored) {
        }
    }

    protected static void writeBoolean(Boolean value, String end) {
        if (write == null) {
            startOutput();
        }
        try {
            write.write(value ? "true" : "false");
            write.write(end);
        } catch (Exception ignored) {
        }
    }

    protected static void writeChar(char word, String end) {
        if (write == null) {
            startOutput();
        }
        try {
            write.write(word);
            write.write(end);
        } catch (Exception ignored) {
        }
    }

    protected static void writeChar(Character word, String end) {
        if (write == null) {
            startOutput();
        }
        try {
            write.write(word);
            write.write(end);
        } catch (Exception ignored) {
        }
    }

    protected static void writeEnter() {
        if (write == null) {
            startOutput();
        }
        try {
            write.newLine();
        } catch (Exception ignored) {
        }
    }

    protected static void print(boolean exit) throws Exception {
        if (exit) {
            print();
        } else {
            write.flush();
        }
    }

    protected static void print() throws Exception {
        if (write == null) {
            return;
        }
        write.flush();
        if (read != null) {
            read.close();
        }
        write.close();
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Scanner;

public class A679 {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader obj=new BufferedReader(new InputStreamReader(System.in));
		int t=Integer.parseInt(obj.readLine());
		while(t-->0)
		{
			String[] s=obj.readLine().split(" ");
			int n=Integer.parseInt(s[0]);
			int m=Integer.parseInt(s[1]);
			int[][] a=new int[n][m];
			int[] col=new int[(n*m)+1];
			int[] row=new int[(n*m)+1];
			for(int i=0;i<n;i++)
			{
				String[] s0=obj.readLine().split(" ");
				for(int j=0;j<m;j++)
				{
					int ele=Integer.parseInt(s0[j]);
					col[ele]=j;
				}
			}
			for(int i=0;i<m;i++)
			{
				String[] s0=obj.readLine().split(" ");
				for(int j=0;j<n;j++)
				{
					int ele=Integer.parseInt(s0[j]);
					row[ele]=j;
				}
			}
			for(int i=1;i<(n*m)+1;i++)
			{
				a[row[i]][col[i]]=i;
			}
			for(int i=0;i<n;i++)
			{
				for(int j=0;j<m;j++)
				{
					System.out.print(a[i][j]+" ");
				}
				System.out.println();
			}
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Scanner;

public class A679 {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader obj=new BufferedReader(new InputStreamReader(System.in));
		int t=Integer.parseInt(obj.readLine());
		while(t-->0)
		{
			String[] s=obj.readLine().split(" ");
			int n=Integer.parseInt(s[0]);
			int m=Integer.parseInt(s[1]);
			int[][] a=new int[n][m];
			int[] col=new int[(n*m)+1];
			int[] row=new int[(n*m)+1];
			for(int i=0;i<n;i++)
			{
				String[] s0=obj.readLine().split(" ");
				for(int j=0;j<m;j++)
				{
					int ele=Integer.parseInt(s0[j]);
					col[ele]=j;
				}
			}
			for(int i=0;i<m;i++)
			{
				String[] s0=obj.readLine().split(" ");
				for(int j=0;j<n;j++)
				{
					int ele=Integer.parseInt(s0[j]);
					row[ele]=j;
				}
			}
			for(int i=1;i<(n*m)+1;i++)
			{
				a[row[i]][col[i]]=i;
			}
			for(int i=0;i<n;i++)
			{
				StringBuilder sb=new StringBuilder();
				for(int j=0;j<m;j++)
				{
					sb.append(a[i][j]+" ");
				}
				System.out.println(sb);
			}
		}
	}
}


import java.util.Scanner;

public class Task2 {

	static StringBuilder result = new StringBuilder();

	public static void main(String[] args) {

		Scanner scn = new Scanner(System.in);

		int T = scn.nextInt();

		for(int i = 0; i < T; i++) resolve(scn);

		System.out.println(result);
	}

	static void resolve(Scanner scn) {

		int n = scn.nextInt();
		int m = scn.nextInt();

		int[][] rowsN = new int[n][m];
		int[][] colsM = new int[m][n];

		for(int i = 0; i < n; i++) {

			for(int j = 0; j < m; j++) {

				rowsN[i][j] = scn.nextInt();
			}
		}

		for(int i = 0; i < m; i++) {

			for(int j = 0; j < n; j++) {

				colsM[i][j] = scn.nextInt();
			}
		}

		find(rowsN, colsM);
	}

	static void find(int[][] strokes, int[][] rows) {

		int[] row = rows[0];

		for(int i = 0; i < row.length; i++) {

			for(int j = 0; j < strokes.length; j++) {

				if(found(row[i], strokes[j])) printArray(strokes[j]);
			}
		}
	}

	static void printArray(int[] a) {

		for(int i = 0; i < a.length; i++) {

			result.append(a[i]);

			if(i != a.length - 1) result.append(" ");
		}

		result.append(System.getProperty("line.separator"));
	}

	static boolean found(int num, int[] array) {

		for(int n : array) if(num == n) return true;

		return false;
	}
}


import java.io.PrintWriter;
import java.util.Scanner;

public class T3 {

    public static void main (String[] args) throws java.lang.Exception
{
    Scanner sc = new Scanner(System.in);
    int t=sc.nextInt();
    PrintWriter pw=new PrintWriter(System.out);

    while(t-->0)
    {
        int n=sc.nextInt();
        int m=sc.nextInt();
        int[][] arr1=new int[n][m];
        int[][] arr2=new int[m][n];

        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                arr1[i][j]=sc.nextInt();
            }
        }
        int index=0;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                arr2[i][j]=sc.nextInt();
                if(arr2[i][j]==arr1[0][0])
                {
                    index=i;
                }
            }
        }

        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)

            {

                if(arr2[index][i]==arr1[j][0])
                {
                    for(int k=0;k<m;k++)
                    {

                        pw.print(arr1[j][k]+" ");
                    }

                    pw.println();
                    break;
                }
            }

        }
    }
    pw.flush();

}
}