import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.math.BigInteger;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;

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

class TaskE {
	int sx, sy;
	int[][] start;
	List<IntPair> answer;

    public void solve(int testNumber, InputReader in, OutputWriter out) {
		int rowCount = in.readInt();
		int columnCount = in.readInt();
		start = IOUtils.readIntTable(in, rowCount, columnCount);
		int[][] target = IOUtils.readIntTable(in, rowCount, columnCount);
		if (rowCount == 1) {
			int from = 0;
			int to = columnCount - 1;
			while (start[0][from] == target[0][from]) {
				from++;
			}
			while (start[0][to] == target[0][to]) {
				to--;
			}
			if (start[0][from] == target[0][to]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[0][j + 1] != target[0][j]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = from; j <= to; j++) {
						out.printLine(1, j + 1);
					}
					return;
				}
			}
			if (start[0][to] == target[0][from]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[0][j] != target[0][j + 1]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = to; j >= from; j--) {
						out.printLine(1, j + 1);
					}
					return;
				}
			}
			out.printLine(-1);
			return;
		}
		if (columnCount == 1) {
			int from = 0;
			int to = rowCount - 1;
			while (start[from][0] == target[from][0]) {
				from++;
			}
			while (start[to][0] == target[to][0]) {
				to--;
			}
			if (start[from][0] == target[to][0]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[j + 1][0] != target[j][0]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = from; j <= to; j++) {
						out.printLine(j + 1, 1);
					}
					return;
				}
			}
			if (start[to][0] == target[from][0]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[j][0] != target[j + 1][0]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = to; j >= from; j--) {
						out.printLine(j + 1, 1);
					}
					return;
				}
			}
			out.printLine(-1);
			return;
		}
		sx = -1;
		sy = -1;
		answer = new ArrayList<>();
		for (int i = 0; i < rowCount && sx == -1; i++) {
			for (int j = 0; j < columnCount; j++) {
				if (start[i][j] == target[0][0]) {
					sx = i;
					sy = j;
					break;
				}
			}
		}
		if (sx == -1) {
			out.printLine(-1);
			return;
		}
		answer.add(new IntPair(sx, sy));
		for (int i = rowCount - 1; i >= 2; i--) {
			for (int j = columnCount - 1; j >= 0; j--) {
				int cx = -1;
				int cy = -1;
				for (int k = 0; k < i && cx == -1; k++) {
					for (int l = 0; l < columnCount; l++) {
						if (start[k][l] == target[i][j] && (k != sx || l != sy)) {
							cx = k;
							cy = l;
							break;
						}
					}
				}
				if (cx == -1) {
					for (int k = 0; k <= j; k++) {
						if (start[i][k] == target[i][j] && (i != sx || k != sy)) {
							cx = i;
							cy = k;
							break;
						}
					}
					if (cx == -1) {
						out.printLine(-1);
						return;
					}
				}
				if (cx == i && cy == j) {
					continue;
				}
				if (cy != 0) {
					if (cx == sx) {
						if (sx == 0) {
							go(sx + 1, sy);
						} else {
							go(sx - 1, sy);
						}
					}
					for (int k = sy - 1; k >= 0; k--) {
						go(sx, k);
					}
					for (int k = sx + 1; k <= cx; k++) {
						go(k, sy);
					}
					for (int k = sx - 1; k >= cx; k--) {
						go(k, sy);
					}
					for (int k = 1; k <= cy; k++) {
						go(sx, k);
					}
					cy--;
					while (cy > 0) {
						if (sx == 0) {
							go(sx + 1, sy - 1);
							go(sx - 1, sy - 1);
							go(sx, sy + 1);
						} else {
							go(sx - 1, sy - 1);
							go(sx + 1, sy - 1);
							go(sx, sy + 1);
						}
						cy--;
					}
				} else {
					while (sy > 1) {
						go(sx, sy - 1);
					}
					if (sy == 0) {
						go(sx, sy + 1);
					}
					while (sx < cx) {
						go(sx + 1, sy);
					}
					while (sx > cx) {
						go(sx - 1, sy);
					}
				}
				if (cx < i) {
					go(sx + 1, sy - 1);
					go(sx - 1, sy);
					cx++;
					while (cx < i) {
						go(sx + 1, sy + 1);
						go(sx + 1, sy - 1);
						go(sx - 1, sy);
						cx++;
					}
				} else {
					go(sx - 1, sy - 1);
				}
				if (cy < j) {
					go(sx + 1, sy + 1);
					go(sx, sy - 1);
					cy++;
					while (cy < j) {
						go(sx - 1, sy + 1);
						go(sx + 1, sy + 1);
						go(sx, sy - 1);
						cy++;
					}
				}
			}
		}
		for (int i = columnCount - 1; i >= 2; i--) {
			for (int j = 1; j >= 0; j--) {
				int cx = -1;
				int cy = -1;
				for (int k = 0; k < i && cx == -1; k++) {
					for (int l = 0; l < 2; l++) {
						if (start[l][k] == target[j][i] && (l != sx || k != sy)) {
							cx = l;
							cy = k;
						}
					}
				}
				if (cx == -1) {
					for (int k = 0; k <= j; k++) {
						if (start[k][i] == target[j][i] && (k != sx || i != sy)) {
							cx = k;
							cy = i;
						}
					}
					if (cx == -1) {
						out.printLine(-1);
						return;
					}
				}
				if (cx == j && cy == i) {
					continue;
				}
				while (cy - sy > 1) {
					go(sx, sy + 1);
				}
				while (sy - cy > 1) {
					go(sx, sy - 1);
				}
				go(cx ^ 1, cy);
				if (cx != j) {
					go(cx, cy);
					cx ^= 1;
				}
				if (cy < i) {
					go(cx, cy + 1);
					go(cx, cy);
					cy++;
					while (cy < i) {
						go(sx ^ 1, sy + 1);
						go(sx ^ 1, sy + 1);
						go(sx, sy - 1);
						cy++;
					}
				}
			}
		}
		if (sx != 0 || sy != 0) {
			go(0, 0);
		}
		if (start[1][1] != target[1][1]) {
			if (start[0][1] == target[1][1]) {
				go(0, 1);
				go(1, 1);
				go(0, 0);
			} else if (start[1][0] == target[1][1]) {
				go(1, 0);
				go(1, 1);
				go(0, 0);
			} else {
				out.printLine(-1);
				return;
			}
		}
		if (start[0][1] != target[0][1]) {
			if (start[1][0] == target[0][1]) {
				go(1, 0);
				go(0, 1);
				go(0, 0);
			} else {
				out.printLine(-1);
				return;
			}
		}
		if (start[1][0] != target[1][0]) {
			out.printLine(-1);
			return;
		}
		out.printLine(answer.size() - 1);
		for (IntPair pair : answer) {
			out.printLine(pair.first + 1, pair.second + 1);
		}
    }

	private void go(int nx, int ny) {
		int temp = start[sx][sy];
		start[sx][sy] = start[nx][ny];
		start[nx][ny] = temp;
		sx = nx;
		sy = ny;
		answer.add(new IntPair(nx, ny));
	}
}

class IntPair implements Comparable<IntPair> {
	public final int first, second;

	public IntPair(int first, int second) {
		this.first = first;
		this.second = second;
	}

	public String toString() {
		return "(" + first + "," + second + ")";
	}

	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;

		IntPair intPair = (IntPair) o;

		return first == intPair.first && second == intPair.second;

	}

	public int hashCode() {
		int result = first;
		result = 31 * result + second;
		return result;
	}

	public int compareTo(IntPair o) {
		if (first < o.first)
			return -1;
		if (first > o.first)
			return 1;
		if (second < o.second)
			return -1;
		if (second > o.second)
			return 1;
		return 0;
	}
}

class InputReader {

	private InputStream stream;
	private byte[] buf = new byte[1024];
	private int curChar;
	private int numChars;
	private SpaceCharFilter filter;

	public InputReader(InputStream stream) {
		this.stream = stream;
	}

	public int read() {
		if (numChars == -1)
			throw new InputMismatchException();
		if (curChar >= numChars) {
			curChar = 0;
			try {
				numChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (numChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int readInt() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			if (c < '0' || c > '9')
				throw new InputMismatchException();
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public boolean isSpaceChar(int c) {
		if (filter != null)
			return filter.isSpaceChar(c);
		return isWhitespace(c);
	}

	public static boolean isWhitespace(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	public interface SpaceCharFilter {
		public boolean isSpaceChar(int ch);
	}
}

class OutputWriter {
	private final PrintWriter writer;

	public OutputWriter(OutputStream outputStream) {
		writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
	}

	public OutputWriter(Writer writer) {
		this.writer = new PrintWriter(writer);
	}

	public void print(Object...objects) {
		for (int i = 0; i < objects.length; i++) {
			if (i != 0)
				writer.print(' ');
			writer.print(objects[i]);
		}
	}

	public void printLine(Object...objects) {
		print(objects);
		writer.println();
	}

	public void close() {
		writer.close();
	}

	public void printLine(int i) {
		writer.println(i);
	}
}

class IOUtils {

	public static int[] readIntArray(InputReader in, int size) {
		int[] array = new int[size];
		for (int i = 0; i < size; i++)
			array[i] = in.readInt();
		return array;
	}

	public static int[][] readIntTable(InputReader in, int rowCount, int columnCount) {
		int[][] table = new int[rowCount][];
		for (int i = 0; i < rowCount; i++)
			table[i] = readIntArray(in, columnCount);
		return table;
	}

}


import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;
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
 */
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);
		TaskE solver = new TaskE();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskE {

    private int ci;
    private int cj;
    private int reslen;
    private int[] resi;
    private int[] resj;
    private boolean[][] frozen;
    private int[][] di;
    private int[][] dj;
    private int[][] ri;
    private int[][] rj;
    private int[] wi;
    private int[] wj;
    private int[][] nexti;
    private int[][] nextj;
    private int[] seqi;
    private int[] seqj;
    private int nseq;
    private int si;
    private int sj;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt();
        int m = in.nextInt();
        int[][] start = new int[n][m];
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < m; ++j)
                start[i][j] = in.nextInt();
        int[][] finish = new int[n][m];
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < m; ++j)
                finish[i][j] = in.nextInt();
        if (n == 1 || m == 1) {
            solveForOne(n, m, start, finish, out);
        } else {
            solveForMany(n, m, start, finish, out);
        }
    }

    int[][] start;
    int n;
    int m;

    private void solveForMany(int n, int m, int[][] start, int[][] finish, PrintWriter out) {
        this.n = n;
        this.m = m;
        this.start = start;
        di = new int[n][m];
        dj = new int[n][m];
        ri = new int[n][m];
        rj = new int[n][m];
        wi = new int[1000];
        wj = new int[1000];
        nexti = new int[n][m];
        nextj = new int[n][m];
        Arrays.fill(wi, -1);
        Arrays.fill(wj, -1);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                nexti[i][j] = wi[finish[i][j]];
                nextj[i][j] = wj[finish[i][j]];
                wi[finish[i][j]] = i;
                wj[finish[i][j]] = j;
            }
        }
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                int zi = wi[start[i][j]];
                int zj = wj[start[i][j]];
                if (zi < 0) {
                    out.println(-1);
                    return;
                }
                di[i][j] = zi;
                dj[i][j] = zj;
                ri[zi][zj] = i;
                rj[zi][zj] = j;
                wi[start[i][j]] = nexti[zi][zj];
                wj[start[i][j]] = nextj[zi][zj];
            }
        }
        seqi = new int[n * m];
        seqj = new int[n * m];
        nseq = 0;
        si = 0;
        sj = 0;
        while (nseq < n * m) {
            if (n - si > m - sj) {
                for (int t = sj; t < m; ++t) {
                    seqi[nseq] = si;
                    seqj[nseq] = t;
                    ++nseq;
                }
                ++si;
                if (si > n) throw new RuntimeException();
            } else {
                for (int t = si; t < n; ++t) {
                    seqi[nseq] = t;
                    seqj[nseq] = sj;
                    ++nseq;
                }
                ++sj;
                if (sj > m) throw new RuntimeException();
            }
        }
        if (si < n && sj < m) throw new RuntimeException();
        ci = di[n - 1][m - 1];
        cj = dj[n - 1][m - 1];
        reslen = 1;
        resi = new int[(int) 1e6 + 10];
        resj = new int[(int) 1e6 + 10];
        resi[0] = ci;
        resj[0] = cj;
        frozen = new boolean[n][m];
        qi = new int[n * m];
        qj = new int[n * m];
        pi = new int[n][m];
        pj = new int[n][m];
        lastGeneration = 0;
        generation = new int[n][m];
        for (int seqpos = 0; seqpos < nseq - 1; ++seqpos) {
            int ti = seqi[seqpos];
            int tj = seqj[seqpos];
            while (ti != di[ti][tj] || tj != dj[ti][tj]) {
                si = di[ti][tj];
                sj = dj[ti][tj];
                frozen[si][sj] = true;
                int ni;
                int nj;
                if (Math.abs(si - ti) > Math.abs(sj - tj)) {
                    ni = si + sign(ti - si);
                    nj = sj;
                } else if (Math.abs(si - ti) < Math.abs(sj - tj)) {
                    ni = si;
                    nj = sj + sign(tj - sj);
                } else {
                    ni = si + sign(ti - si);
                    nj = sj + sign(tj - sj);
                }
                if (frozen[ni][nj]) throw new RuntimeException();
                moveTo(ni, nj);
                frozen[si][sj] = false;
                oneSwap(si, sj);
            }
            frozen[ti][tj] = true;
        }
        out.println(reslen - 1);
        for (int i = 0; i < reslen; ++i) {
            out.println((resi[i] + 1) + " " + (resj[i] + 1));
        }
    }

    private void oneSwap(int si, int sj) {
        if (frozen[ci][cj]) throw new RuntimeException();
        if (frozen[si][sj]) throw new RuntimeException();
        if (ci == si && cj == sj) throw new RuntimeException();
        if (Math.abs(ci - si) > 1 || Math.abs(cj - sj) > 1) throw new RuntimeException();
        int tmp = start[ci][cj];
        start[ci][cj] = start[si][sj];
        start[si][sj] = tmp;
        tmp = ri[ci][cj];
        ri[ci][cj] = ri[si][sj];
        ri[si][sj] = tmp;
        tmp = rj[ci][cj];
        rj[ci][cj] = rj[si][sj];
        rj[si][sj] = tmp;
        di[ri[ci][cj]][rj[ci][cj]] = ci;
        dj[ri[ci][cj]][rj[ci][cj]] = cj;
        di[ri[si][sj]][rj[si][sj]] = si;
        dj[ri[si][sj]][rj[si][sj]] = sj;
        ci = si;
        cj = sj;
        resi[reslen] = si;
        resj[reslen] = sj;
        ++reslen;
    }

    int[][] generation;
    int[] qi;
    int[] qj;
    int[][] pi;
    int[][] pj;
    int lastGeneration;

    private void moveTo(int ni, int nj) {
        int qt = 0;
        int qh = 1;
        qi[0] = ni;
        qj[0] = nj;
        ++lastGeneration;
        generation[ni][nj] = lastGeneration;
        pi[ni][nj] = -1;
        pj[ni][nj] = -1;
        while (generation[ci][cj] < lastGeneration) {
            if (qt == qh) throw new RuntimeException();
            ni = qi[qt];
            nj = qj[qt];
            ++qt;
            for (int di = -1; di <= 1; ++di)
                for (int dj = -1; dj <= 1; ++dj) {
                    int mi = ni + di;
                    int mj = nj + dj;
                    if (mi >= 0 && mi < n && mj >= 0 && mj < m && !frozen[mi][mj] && generation[mi][mj] < lastGeneration) {
                        generation[mi][mj] = lastGeneration;
                        pi[mi][mj] = ni;
                        pj[mi][mj] = nj;
                        qi[qh] = mi;
                        qj[qh] = mj;
                        ++qh;
                    }
                }
        }
        while (pi[ci][cj] >= 0) {
            oneSwap(pi[ci][cj], pj[ci][cj]);
        }
    }

    private void solveForOne(int n, int m, int[][] start, int[][] finish, PrintWriter out) {
        for (int si = 0; si < n; ++si)
            for (int sj = 0; sj < m; ++sj)
                for (int ti = 0; ti < n; ++ti)
                    outer: for (int tj = 0; tj < m; ++tj) {
                        int di = sign(ti - si);
                        int dj = sign(tj - sj);
                        if ((di == 0) ^ (dj == 0)) {
                            for (int ci = 0; ci < n; ++ci) {
                                for (int cj = 0; cj < m; ++cj) {
                                    int w;
                                    if (ci == ti && cj == tj) {
                                        w = start[si][sj];
                                    } else if (ci == si && cj == sj) {
                                        w = start[ci + di][cj + dj];
                                    } else if (ci <= si && cj <= sj && ci <= ti && cj <= tj) {
                                        w = start[ci][cj];
                                    } else if (ci >= si && cj >= sj && ci >= ti && cj >= tj) {
                                        w = start[ci][cj];
                                    } else {
                                        w = start[ci + di][cj + dj];
                                    }
                                    if (w != finish[ci][cj]) {
                                        continue outer;
                                    }
                                }
                            }
                            out.println(Math.abs(ti - si) + Math.abs(tj - sj));
                            out.println((si + 1) + " " + (sj + 1));
                            int ci = si;
                            int cj = sj;
                            do {
                                ci += di;
                                cj += dj;
                                out.println((ci + 1) + " " + (cj + 1));
                            } while (ci != ti || cj != tj);
                            return;
                        }
                    }
        out.println(-1);
    }

    private int sign(int x) {
        if (x == 0) return 0; else if (x > 0) return 1; else return -1;
    }
}

class InputReader {
    private final BufferedReader reader;
    private StringTokenizer tokenizer;

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

    public String nextLine() {
        try {
            return reader.readLine();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            tokenizer = new StringTokenizer(nextLine());
        }
        return tokenizer.nextToken();
    }

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

}


import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;
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
 */
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);
		TaskE solver = new TaskE();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskE {

    private int ci;
    private int cj;
    private int reslen;
    private int[] resi;
    private int[] resj;
    private boolean[][] frozen;
    private int[][] di;
    private int[][] dj;
    private int[][] ri;
    private int[][] rj;
    private int[] wi;
    private int[] wj;
    private int[][] nexti;
    private int[][] nextj;
    private int[] seqi;
    private int[] seqj;
    private int nseq;
    private int si;
    private int sj;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt();
        int m = in.nextInt();
        int[][] start = new int[n][m];
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < m; ++j)
                start[i][j] = in.nextInt();
        int[][] finish = new int[n][m];
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < m; ++j)
                finish[i][j] = in.nextInt();
        if (n == 1 || m == 1) {
            solveForOne(n, m, start, finish, out);
        } else {
            solveForMany(n, m, start, finish, out);
        }
    }

    int[][] start;
    int n;
    int m;

    private void solveForMany(int n, int m, int[][] start, int[][] finish, PrintWriter out) {
        this.n = n;
        this.m = m;
        this.start = start;
        di = new int[n][m];
        dj = new int[n][m];
        ri = new int[n][m];
        rj = new int[n][m];
        wi = new int[1000];
        wj = new int[1000];
        nexti = new int[n][m];
        nextj = new int[n][m];
        Arrays.fill(wi, -1);
        Arrays.fill(wj, -1);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                nexti[i][j] = wi[finish[i][j]];
                nextj[i][j] = wj[finish[i][j]];
                wi[finish[i][j]] = i;
                wj[finish[i][j]] = j;
            }
        }
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                int zi = wi[start[i][j]];
                int zj = wj[start[i][j]];
                if (zi < 0) {
                    out.println(-1);
                    return;
                }
                ri[i][j] = zi;
                rj[i][j] = zj;
                di[zi][zj] = i;
                dj[zi][zj] = j;
                wi[start[i][j]] = nexti[zi][zj];
                wj[start[i][j]] = nextj[zi][zj];
            }
        }
        seqi = new int[n * m];
        seqj = new int[n * m];
        nseq = 0;
        si = 0;
        sj = 0;
        while (nseq < n * m) {
            if (n - si > m - sj) {
                for (int t = sj; t < m; ++t) {
                    seqi[nseq] = si;
                    seqj[nseq] = t;
                    ++nseq;
                }
                ++si;
                if (si > n) throw new RuntimeException();
            } else {
                for (int t = si; t < n; ++t) {
                    seqi[nseq] = t;
                    seqj[nseq] = sj;
                    ++nseq;
                }
                ++sj;
                if (sj > m) throw new RuntimeException();
            }
        }
        if (si < n && sj < m) throw new RuntimeException();
        ci = di[n - 1][m - 1];
        cj = dj[n - 1][m - 1];
        reslen = 1;
        resi = new int[(int) 1e6 + 10];
        resj = new int[(int) 1e6 + 10];
        resi[0] = ci;
        resj[0] = cj;
        frozen = new boolean[n][m];
        qi = new int[n * m];
        qj = new int[n * m];
        pi = new int[n][m];
        pj = new int[n][m];
        lastGeneration = 0;
        generation = new int[n][m];
        for (int seqpos = 0; seqpos < nseq - 1; ++seqpos) {
            int ti = seqi[seqpos];
            int tj = seqj[seqpos];
            while (ti != di[ti][tj] || tj != dj[ti][tj]) {
                si = di[ti][tj];
                sj = dj[ti][tj];
                frozen[si][sj] = true;
                int ni;
                int nj;
                if (Math.abs(si - ti) > Math.abs(sj - tj)) {
                    ni = si + sign(ti - si);
                    nj = sj;
                } else if (Math.abs(si - ti) < Math.abs(sj - tj)) {
                    ni = si;
                    nj = sj + sign(tj - sj);
                } else {
                    ni = si + sign(ti - si);
                    nj = sj + sign(tj - sj);
                }
                if (frozen[ni][nj]) throw new RuntimeException();
                moveTo(ni, nj);
                frozen[si][sj] = false;
                oneSwap(si, sj);
            }
            frozen[ti][tj] = true;
        }
        out.println(reslen - 1);
        for (int i = 0; i < reslen; ++i) {
            out.println((resi[i] + 1) + " " + (resj[i] + 1));
        }
    }

    private void oneSwap(int si, int sj) {
        if (frozen[ci][cj]) throw new RuntimeException();
        if (frozen[si][sj]) throw new RuntimeException();
        if (ci == si && cj == sj) throw new RuntimeException();
        if (Math.abs(ci - si) > 1 || Math.abs(cj - sj) > 1) throw new RuntimeException();
        int tmp = start[ci][cj];
        start[ci][cj] = start[si][sj];
        start[si][sj] = tmp;
        tmp = ri[ci][cj];
        ri[ci][cj] = ri[si][sj];
        ri[si][sj] = tmp;
        tmp = rj[ci][cj];
        rj[ci][cj] = rj[si][sj];
        rj[si][sj] = tmp;
        di[ri[ci][cj]][rj[ci][cj]] = ci;
        dj[ri[ci][cj]][rj[ci][cj]] = cj;
        di[ri[si][sj]][rj[si][sj]] = si;
        dj[ri[si][sj]][rj[si][sj]] = sj;
        ci = si;
        cj = sj;
        resi[reslen] = si;
        resj[reslen] = sj;
        ++reslen;
    }

    int[][] generation;
    int[] qi;
    int[] qj;
    int[][] pi;
    int[][] pj;
    int lastGeneration;

    private void moveTo(int ni, int nj) {
        int qt = 0;
        int qh = 1;
        qi[0] = ni;
        qj[0] = nj;
        ++lastGeneration;
        generation[ni][nj] = lastGeneration;
        pi[ni][nj] = -1;
        pj[ni][nj] = -1;
        while (generation[ci][cj] < lastGeneration) {
            if (qt == qh) throw new RuntimeException();
            ni = qi[qt];
            nj = qj[qt];
            ++qt;
            for (int di = -1; di <= 1; ++di)
                for (int dj = -1; dj <= 1; ++dj) {
                    int mi = ni + di;
                    int mj = nj + dj;
                    if (mi >= 0 && mi < n && mj >= 0 && mj < m && !frozen[mi][mj] && generation[mi][mj] < lastGeneration) {
                        generation[mi][mj] = lastGeneration;
                        pi[mi][mj] = ni;
                        pj[mi][mj] = nj;
                        qi[qh] = mi;
                        qj[qh] = mj;
                        ++qh;
                    }
                }
        }
        while (pi[ci][cj] >= 0) {
            oneSwap(pi[ci][cj], pj[ci][cj]);
        }
    }

    private void solveForOne(int n, int m, int[][] start, int[][] finish, PrintWriter out) {
        for (int si = 0; si < n; ++si)
            for (int sj = 0; sj < m; ++sj)
                for (int ti = 0; ti < n; ++ti)
                    outer: for (int tj = 0; tj < m; ++tj) {
                        int di = sign(ti - si);
                        int dj = sign(tj - sj);
                        if ((di == 0) ^ (dj == 0)) {
                            for (int ci = 0; ci < n; ++ci) {
                                for (int cj = 0; cj < m; ++cj) {
                                    int w;
                                    if (ci == ti && cj == tj) {
                                        w = start[si][sj];
                                    } else if (ci == si && cj == sj) {
                                        w = start[ci + di][cj + dj];
                                    } else if (ci <= si && cj <= sj && ci <= ti && cj <= tj) {
                                        w = start[ci][cj];
                                    } else if (ci >= si && cj >= sj && ci >= ti && cj >= tj) {
                                        w = start[ci][cj];
                                    } else {
                                        w = start[ci + di][cj + dj];
                                    }
                                    if (w != finish[ci][cj]) {
                                        continue outer;
                                    }
                                }
                            }
                            out.println(Math.abs(ti - si) + Math.abs(tj - sj));
                            out.println((si + 1) + " " + (sj + 1));
                            int ci = si;
                            int cj = sj;
                            do {
                                ci += di;
                                cj += dj;
                                out.println((ci + 1) + " " + (cj + 1));
                            } while (ci != ti || cj != tj);
                            return;
                        }
                    }
        out.println(-1);
    }

    private int sign(int x) {
        if (x == 0) return 0; else if (x > 0) return 1; else return -1;
    }
}

class InputReader {
    private final BufferedReader reader;
    private StringTokenizer tokenizer;

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

    public String nextLine() {
        try {
            return reader.readLine();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            tokenizer = new StringTokenizer(nextLine());
        }
        return tokenizer.nextToken();
    }

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

}


#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <ctime>
#include <map>
#define fi first
#define se second
#define PA pair<int,int>
#define VI vector<int>
#define VP vector<PA >
#define mk(x,y) make_pair(x,y)
#define N 40
#define For(i,x,y) for (i=x;i<=y;i++)
using namespace std;
const int a1[8]={-1,-1,-1,0,0,1,1,1},a2[8]={-1,0,1,-1,1,-1,0,1};
int i,j,k,n,m,_,num;
int a[N][N],b[N][N],s[1000],ff[N][N];
map<PA,int> h;
PA O;
VP an,tmp;
inline bool ju(int a[N],int b[N]) {
	int i;
	For(i,1,m) if (a[i]!=b[i]) return 0;
	return 1;
}
inline void print(int _,int x,int y) {
	if (_) swap(x,y);
	printf("%d %d\n",x,y);
}
inline void work1(int _) {
	For(i,1,m) {
		For(j,1,i-1) {
			int h[N];
			For(k,1,j-1) h[k]=a[1][k];
			h[j]=a[1][i];
			For(k,j,i-1) h[k+1]=a[1][k];
			For(k,i+1,m) h[k]=a[1][k];
			if (ju(h,b[1])) {
				printf("%d\n",i-j);
				for (k=i;k>=j;k--) print(_,1,k);
				exit(0);
			}
		}
		For(j,i+1,m) {
			int h[N];
			For(k,1,i-1) h[k]=a[1][k];
			For(k,i,j-1) h[k]=a[1][k+1];
			h[j]=a[1][i];
			For(k,j+1,m) h[k]=a[1][k];
			if (ju(h,b[1])) {
				printf("%d\n",j-i);
				For(k,i,j) print(_,1,k);
				exit(0);
			}
		}
	}
	printf("-1\n");
	exit(0);
}
inline void rev() {
	int i,j,c[N][N],d[N][N];
	For(i,1,n)For(j,1,m) c[i][j]=a[j][i],d[i][j]=b[j][i];
	swap(n,m);
	For(i,1,n)For(j,1,m) a[i][j]=c[i][j],b[i][j]=d[i][j];
	_^=1;
	swap(O.fi,O.se);
}
inline void jin(PA O) {
	if (_) swap(O.fi,O.se);
	an.push_back(O);
}
inline void print() {
	int i;
	printf("%d\n",an.size()-1);
	for (i=0;i<an.size();i++) printf("%d %d\n",an[i].fi,an[i].se);
}
inline void dong(PA &u) {
	jin(u);
	swap(O,u);
	swap(a[O.fi][O.se],a[u.fi][u.se]);
}
bool dfs(PA O,PA goal) {
	int i;
	if (O==goal) return 1;
	if (h[O]==num) return 0;
	h[O]=num;
	For(i,0,7) {
		int x=O.fi+a1[i],y=O.se+a2[i];
		PA u=mk(x,y);
		if (x&&y&&x<=n&&y<=m&&!ff[x][y])
			if (dfs(u,goal)) {
				tmp.push_back(u);
				return 1;
			}
	}
	return 0;
}
inline void gao(PA O,PA goal) {
	++num;
	tmp.clear();
	dfs(O,goal);
	int i;
	for (i=tmp.size()-1;i>=0;i--) {
		PA A=tmp[i];
		dong(A);
	}
}
inline void zou(PA u,PA goal) {
	for (;u.se<m;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi,u.se+1));
		ff[u.fi][u.se]=0;
		dong(u);
	}
	for (;u.fi<n;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi+1,u.se));
		ff[u.fi][u.se]=0;
		dong(u);
	}
	for (;u.se>goal.se;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi,u.se-1));
		ff[u.fi][u.se]=0;
		dong(u);
	}
}
inline void work() {
	For(i,1,n)For(j,1,m) if (a[i][j]==b[1][m]) {
		O=mk(i,j);
		a[i][j]=0;
		goto yes;
	}
	yes:;
	jin(O);
	for (;;) {
		if (n<m) rev();
		if (n==1) break;
		memset(ff,0,sizeof(ff));
		For(i,1,m) {
			PA w;
			For(j,1,n)For(k,1,m) if (!ff[j][k]&&a[j][k]==b[n][i]) {
				w=mk(j,k);
				goto jie;
			}
			jie:;
			zou(w,mk(n,i));
			ff[n][i]=1;
		}
		n--;
	}
	print();
}
int main() {
	scanf("%d%d",&n,&m);
	For(i,1,n)For(j,1,m) scanf("%d",&a[i][j]),s[a[i][j]]++;
	For(i,1,n)For(j,1,m) scanf("%d",&b[i][j]),s[b[i][j]]--;
	For(i,1,900) if (s[i]) {
		printf("-1\n");
		return 0;
	}
	if (n==1) work1(0);
	if (m==1) {
		For(i,1,n) swap(a[i][1],a[1][i]),swap(b[i][1],b[1][i]);
		swap(n,m);
		work1(1);
	}
	work();
	return 0;
}


#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <ctime>
#include <map>
#define fi first
#define se second
#define PA pair<int,int>
#define VI vector<int>
#define VP vector<PA >
#define mk(x,y) make_pair(x,y)
#define N 40
#define For(i,x,y) for (i=x;i<=y;i++)
using namespace std;
const int a1[8]={-1,-1,-1,0,0,1,1,1},a2[8]={-1,0,1,-1,1,-1,0,1};
int i,j,k,n,m,_,num;
int a[N][N],b[N][N],s[1000],ff[N][N];
map<PA,int> h;
PA O;
VP an,tmp;
inline bool ju(int a[N],int b[N]) {
	int i;
	For(i,1,m) if (a[i]!=b[i]) return 0;
	return 1;
}
inline void print(int _,int x,int y) {
	if (_) swap(x,y);
	printf("%d %d\n",x,y);
}
inline void work1(int _) {
	For(i,1,m) {
		For(j,1,i-1) {
			int h[N];
			For(k,1,j-1) h[k]=a[1][k];
			h[j]=a[1][i];
			For(k,j,i-1) h[k+1]=a[1][k];
			For(k,i+1,m) h[k]=a[1][k];
			if (ju(h,b[1])) {
				printf("%d\n",i-j);
				for (k=i;k>=j;k--) print(_,1,k);
				exit(0);
			}
		}
		For(j,i+1,m) {
			int h[N];
			For(k,1,i-1) h[k]=a[1][k];
			For(k,i,j-1) h[k]=a[1][k+1];
			h[j]=a[1][i];
			For(k,j+1,m) h[k]=a[1][k];
			if (ju(h,b[1])) {
				printf("%d\n",j-i);
				For(k,i,j) print(_,1,k);
				exit(0);
			}
		}
	}
	printf("-1\n");
	exit(0);
}
inline void rev() {
	int i,j,c[N][N],d[N][N];
	For(i,1,n)For(j,1,m) c[i][j]=a[j][i],d[i][j]=b[j][i];
	swap(n,m);
	For(i,1,n)For(j,1,m) a[i][j]=c[i][j],b[i][j]=d[i][j];
	_^=1;
	swap(O.fi,O.se);
}
inline void jin(PA O) {
	if (_) swap(O.fi,O.se);
	an.push_back(O);
}
inline void print() {
	int i;
	printf("%d\n",an.size()-1);
	for (i=0;i<an.size();i++) printf("%d %d\n",an[i].fi,an[i].se);
}
inline void dong(PA &u) {
	jin(u);
	swap(O,u);
	swap(a[O.fi][O.se],a[u.fi][u.se]);
}
bool dfs(PA O,PA goal) {
	int i;
	if (O==goal) return 1;
	if (h[O]==num) return 0;
	h[O]=num;
	For(i,0,7) {
		int x=O.fi+a1[i],y=O.se+a2[i];
		PA u=mk(x,y);
		if (x&&y&&x<=n&&y<=m&&!ff[x][y])
			if (dfs(u,goal)) {
				tmp.push_back(u);
				return 1;
			}
	}
	return 0;
}
inline void gao(PA O,PA goal) {
	++num;
	tmp.clear();
	dfs(O,goal);
	int i;
	for (i=tmp.size()-1;i>=0;i--) {
		PA A=tmp[i];
		dong(A);
	}
}
inline void zou(PA u,PA goal) {
	for (;u.se<m;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi,u.se+1));
		ff[u.fi][u.se]=0;
		dong(u);
	}
	for (;u.fi<n;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi+1,u.se));
		ff[u.fi][u.se]=0;
		dong(u);
	}
	for (;u.se>goal.se;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi,u.se-1));
		ff[u.fi][u.se]=0;
		dong(u);
	}
}
inline void work() {
	For(i,1,n)For(j,1,m) if (a[i][j]==b[1][1]) {
		O=mk(i,j);
		a[i][j]=0;
		goto yes;
	}
	yes:;
	jin(O);
	for (;;) {
		if (n<m) rev();
		if (n==1) break;
		memset(ff,0,sizeof(ff));
		For(i,1,m) {
			PA w;
			For(j,1,n)For(k,1,m) if (!ff[j][k]&&a[j][k]==b[n][i]) {
				w=mk(j,k);
				goto jie;
			}
			jie:;
			zou(w,mk(n,i));
			ff[n][i]=1;
		}
		n--;
	}
	print();
}
int main() {
	scanf("%d%d",&n,&m);
	For(i,1,n)For(j,1,m) scanf("%d",&a[i][j]),s[a[i][j]]++;
	For(i,1,n)For(j,1,m) scanf("%d",&b[i][j]),s[b[i][j]]--;
	For(i,1,900) if (s[i]) {
		printf("-1\n");
		return 0;
	}
	if (n==1) work1(0);
	if (m==1) {
		For(i,1,n) swap(a[i][1],a[1][i]),swap(b[i][1],b[1][i]);
		swap(n,m);
		work1(1);
	}
	work();
	return 0;
}


#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <ctime>
#include <map>
#define fi first
#define se second
#define PA pair<int,int>
#define VI vector<int>
#define VP vector<PA >
#define mk(x,y) make_pair(x,y)
#define N 40
#define For(i,x,y) for (i=x;i<=y;i++)
using namespace std;
const int a1[8]={-1,-1,-1,0,0,1,1,1},a2[8]={-1,0,1,-1,1,-1,0,1};
int i,j,k,n,m,_,num;
int a[N][N],b[N][N],s[1000],ff[N][N],h[N][N];
PA O,g[N*N];
VP an,tmp;
map<PA,PA> fa;
map<PA,int> gg;
inline bool ju(int a[N],int b[N]) {
	int i;
	For(i,1,m) if (a[i]!=b[i]) return 0;
	return 1;
}
inline void print(int _,int x,int y) {
	if (_) swap(x,y);
	printf("%d %d\n",x,y);
}
inline void work1(int _) {
	For(i,1,m) {
		For(j,1,i-1) {
			int h[N];
			For(k,1,j-1) h[k]=a[1][k];
			h[j]=a[1][i];
			For(k,j,i-1) h[k+1]=a[1][k];
			For(k,i+1,m) h[k]=a[1][k];
			if (ju(h,b[1])) {
				printf("%d\n",i-j);
				for (k=i;k>=j;k--) print(_,1,k);
				exit(0);
			}
		}
		For(j,i+1,m) {
			int h[N];
			For(k,1,i-1) h[k]=a[1][k];
			For(k,i,j-1) h[k]=a[1][k+1];
			h[j]=a[1][i];
			For(k,j+1,m) h[k]=a[1][k];
			if (ju(h,b[1])) {
				printf("%d\n",j-i);
				For(k,i,j) print(_,1,k);
				exit(0);
			}
		}
	}
	printf("-1\n");
	exit(0);
}
inline void rev() {
	int i,j,c[N][N],d[N][N];
	For(i,1,n)For(j,1,m) c[j][i]=a[i][j],d[j][i]=b[i][j];
	swap(n,m);
	For(i,1,n)For(j,1,m) a[i][j]=c[i][j],b[i][j]=d[i][j];
	_^=1;
	swap(O.fi,O.se);
}
inline void jin(PA O) {
	if (_) swap(O.fi,O.se);
	an.push_back(O);
}
inline void print() {
	int i;
	printf("%d\n",an.size()-1);
	for (i=0;i<an.size();i++) printf("%d %d\n",an[i].fi,an[i].se);
}
inline void dong(PA &u) {
	jin(u);
	swap(O,u);
	swap(a[O.fi][O.se],a[u.fi][u.se]);
}
void dfs(PA O,PA now) {
	if (O==now) return;
	dfs(O,fa[now]);
	dong(now);
}
inline void bfs(PA O,PA goal) {
	int l,r,i;
	g[l=r=1]=O; gg.clear(); gg[O]=0;
	for (;l<=r;l++) {
		PA A=g[l];
		if (A==goal) {
			dfs(O,goal);
			return;
		}
		For(i,0,7) {
			int x=A.fi+a1[i],y=A.se+a2[i];
			PA u=mk(x,y);
			if (x&&y&&x<=n&&y<=m&&!ff[x][y])
				if (!gg.count(u)) {
					gg[u]=gg[A]+1; fa[u]=A; g[++r]=u;
				}
		}
	}
}
inline void gao(PA O,PA goal) {
	++num;
	tmp.clear();
	bfs(O,goal);
}
inline void zou(PA u,PA goal) {
	for (;u.se<m;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi,u.se+1));
		ff[u.fi][u.se]=0;
		dong(u);
	}
	for (;u.fi<n;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi+1,u.se));
		ff[u.fi][u.se]=0;
		dong(u);
	}
	for (;u.se>goal.se;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi,u.se-1));
		ff[u.fi][u.se]=0;
		dong(u);
	}
}
inline void work() {
	For(i,1,n)For(j,1,m) if (a[i][j]==b[1][2]) {
		O=mk(i,j);
		a[i][j]=0;
		goto yes;
	}
	yes:;
	jin(O);
	for (;;) {
		if (n<m) rev();
		if (n==1) break;
		memset(ff,0,sizeof(ff));
		For(i,1,m) {
			PA w;
			For(j,1,n)For(k,1,m) if (!ff[j][k]&&a[j][k]==b[n][i]) {
				w=mk(j,k);
				goto jie;
			}
			jie:;
			zou(w,mk(n,i));
			ff[n][i]=1;
		}
		n--;
	}
	print();
}
int main() {
	//freopen("472e.in","r",stdin);
	scanf("%d%d",&n,&m);
	For(i,1,n)For(j,1,m) scanf("%d",&a[i][j]),s[a[i][j]]++;
	For(i,1,n)For(j,1,m) scanf("%d",&b[i][j]),s[b[i][j]]--;
	For(i,1,900) if (s[i]) {
		printf("-1\n");
		return 0;
	}
	if (n==1) work1(0);
	if (m==1) {
		For(i,1,n) swap(a[i][1],a[1][i]),swap(b[i][1],b[1][i]);
		swap(n,m);
		work1(1);
	}
	work();
	return 0;
}


#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <ctime>
#include <map>
#define fi first
#define se second
#define PA pair<int,int>
#define VI vector<int>
#define VP vector<PA >
#define mk(x,y) make_pair(x,y)
#define N 40
#define For(i,x,y) for (i=x;i<=y;i++)
using namespace std;
const int a1[8]={-1,-1,-1,0,0,1,1,1},a2[8]={-1,0,1,-1,1,-1,0,1};
int i,j,k,n,m,_,num;
int a[N][N],b[N][N],s[1000],ff[N][N],h[N][N];
PA O,g[N*N];
VP an,tmp;
map<PA,PA> fa;
map<PA,int> gg;
inline bool ju(int a[N],int b[N]) {
	int i;
	For(i,1,m) if (a[i]!=b[i]) return 0;
	return 1;
}
inline void print(int _,int x,int y) {
	if (_) swap(x,y);
	printf("%d %d\n",x,y);
}
inline void work1(int _) {
	For(i,1,m) {
		For(j,1,i-1) {
			int h[N];
			For(k,1,j-1) h[k]=a[1][k];
			h[j]=a[1][i];
			For(k,j,i-1) h[k+1]=a[1][k];
			For(k,i+1,m) h[k]=a[1][k];
			if (ju(h,b[1])) {
				printf("%d\n",i-j);
				for (k=i;k>=j;k--) print(_,1,k);
				exit(0);
			}
		}
		For(j,i+1,m) {
			int h[N];
			For(k,1,i-1) h[k]=a[1][k];
			For(k,i,j-1) h[k]=a[1][k+1];
			h[j]=a[1][i];
			For(k,j+1,m) h[k]=a[1][k];
			if (ju(h,b[1])) {
				printf("%d\n",j-i);
				For(k,i,j) print(_,1,k);
				exit(0);
			}
		}
	}
	printf("-1\n");
	exit(0);
}
inline void rev() {
	int i,j,c[N][N],d[N][N];
	For(i,1,n)For(j,1,m) c[i][j]=a[j][i],d[i][j]=b[j][i];
	swap(n,m);
	For(i,1,n)For(j,1,m) a[i][j]=c[i][j],b[i][j]=d[i][j];
	_^=1;
	swap(O.fi,O.se);
}
inline void jin(PA O) {
	if (_) swap(O.fi,O.se);
	an.push_back(O);
}
inline void print() {
	int i;
	printf("%d\n",an.size()-1);
	for (i=0;i<an.size();i++) printf("%d %d\n",an[i].fi,an[i].se);
}
inline void dong(PA &u) {
	jin(u);
	swap(O,u);
	swap(a[O.fi][O.se],a[u.fi][u.se]);
}
void dfs(PA O,PA now) {
	if (O==now) return;
	dfs(O,fa[now]);
	dong(now);
}
inline void bfs(PA O,PA goal) {
	int l,r,i;
	g[l=r=1]=O; gg.clear(); gg[O]=0;
	for (;l<=r;l++) {
		PA A=g[l];
		if (A==goal) {
			dfs(O,goal);
			return;
		}
		For(i,0,7) {
			int x=A.fi+a1[i],y=A.se+a2[i];
			PA u=mk(x,y);
			if (x&&y&&x<=n&&y<=m&&!ff[x][y])
				if (!gg.count(u)) {
					gg[u]=gg[A]+1; fa[u]=A; g[++r]=u;
				}
		}
	}
}
inline void gao(PA O,PA goal) {
	++num;
	tmp.clear();
	bfs(O,goal);
}
inline void zou(PA u,PA goal) {
	for (;u.se<m;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi,u.se+1));
		ff[u.fi][u.se]=0;
		dong(u);
	}
	for (;u.fi<n;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi+1,u.se));
		ff[u.fi][u.se]=0;
		dong(u);
	}
	for (;u.se>goal.se;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi,u.se-1));
		ff[u.fi][u.se]=0;
		dong(u);
	}
}
inline void work() {
	For(i,1,n)For(j,1,m) if (a[i][j]==b[1][2]) {
		O=mk(i,j);
		a[i][j]=0;
		goto yes;
	}
	yes:;
	jin(O);
	for (;;) {
		if (n<m) rev();
		if (n==1) break;
		memset(ff,0,sizeof(ff));
		For(i,1,m) {
			PA w;
			For(j,1,n)For(k,1,m) if (!ff[j][k]&&a[j][k]==b[n][i]) {
				w=mk(j,k);
				goto jie;
			}
			jie:;
			zou(w,mk(n,i));
			ff[n][i]=1;
		}
		n--;
	}
	print();
}
int main() {
	scanf("%d%d",&n,&m);
	For(i,1,n)For(j,1,m) scanf("%d",&a[i][j]),s[a[i][j]]++;
	For(i,1,n)For(j,1,m) scanf("%d",&b[i][j]),s[b[i][j]]--;
	For(i,1,900) if (s[i]) {
		printf("-1\n");
		return 0;
	}
	if (n==1) work1(0);
	if (m==1) {
		For(i,1,n) swap(a[i][1],a[1][i]),swap(b[i][1],b[1][i]);
		swap(n,m);
		work1(1);
	}
	work();
	return 0;
}


#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <ctime>
#include <map>
#define fi first
#define se second
#define PA pair<int,int>
#define VI vector<int>
#define VP vector<PA >
#define mk(x,y) make_pair(x,y)
#define N 40
#define For(i,x,y) for (i=x;i<=y;i++)
using namespace std;
const int a1[8]={-1,-1,-1,0,0,1,1,1},a2[8]={-1,0,1,-1,1,-1,0,1};
int i,j,k,n,m,_,num;
int a[N][N],b[N][N],s[1000],ff[N][N];
map<PA,int> h;
PA O;
VP an,tmp;
inline bool ju(int a[N],int b[N]) {
	int i;
	For(i,1,m) if (a[i]!=b[i]) return 0;
	return 1;
}
inline void print(int _,int x,int y) {
	if (_) swap(x,y);
	printf("%d %d\n",x,y);
}
inline void work1(int _) {
	For(i,1,m) {
		For(j,1,i-1) {
			int h[N];
			For(k,1,j-1) h[k]=a[1][k];
			h[j]=a[1][i];
			For(k,j,i-1) h[k+1]=a[1][k];
			For(k,i+1,m) h[k]=a[1][k];
			if (ju(h,b[1])) {
				printf("%d\n",i-j);
				for (k=i;k>=j;k--) print(_,1,k);
				exit(0);
			}
		}
		For(j,i+1,m) {
			int h[N];
			For(k,1,i-1) h[k]=a[1][k];
			For(k,i,j-1) h[k]=a[1][k+1];
			h[j]=a[1][i];
			For(k,j+1,m) h[k]=a[1][k];
			if (ju(h,b[1])) {
				printf("%d\n",j-i);
				For(k,i,j) print(_,1,k);
				exit(0);
			}
		}
	}
	printf("-1\n");
	exit(0);
}
inline void rev() {
	int i,j,c[N][N],d[N][N];
	For(i,1,n)For(j,1,m) c[i][j]=a[j][i],d[i][j]=b[j][i];
	swap(n,m);
	For(i,1,n)For(j,1,m) a[i][j]=c[i][j],b[i][j]=d[i][j];
	_^=1;
	swap(O.fi,O.se);
}
inline void jin(PA O) {
	if (_) swap(O.fi,O.se);
	an.push_back(O);
}
inline void print() {
	int i;
	printf("%d\n",an.size()-1);
	for (i=0;i<an.size();i++) printf("%d %d\n",an[i].fi,an[i].se);
}
inline void dong(PA &u) {
	jin(u);
	swap(O,u);
	swap(a[O.fi][O.se],a[u.fi][u.se]);
}
bool dfs(PA O,PA goal) {
	int i;
	if (O==goal) return 1;
	if (h[O]==num) return 0;
	h[O]=num;
	For(i,0,7) {
		int x=O.fi+a1[i],y=O.se+a2[i];
		PA u=mk(x,y);
		if (x&&y&&x<=n&&y<=m&&!ff[x][y])
			if (dfs(u,goal)) {
				tmp.push_back(u);
				return 1;
			}
	}
	return 0;
}
inline void gao(PA O,PA goal) {
	++num;
	tmp.clear();
	dfs(O,goal);
	int i;
	for (i=tmp.size()-1;i>=0;i--) {
		PA A=tmp[i];
		dong(A);
	}
}
inline void zou(PA u,PA goal) {
	for (;u.se<m;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi,u.se+1));
		ff[u.fi][u.se]=0;
		dong(u);
	}
	for (;u.fi<n;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi+1,u.se));
		ff[u.fi][u.se]=0;
		dong(u);
	}
	for (;u.se>goal.se;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi,u.se-1));
		ff[u.fi][u.se]=0;
		dong(u);
	}
}
inline void work() {
	For(i,1,n)For(j,1,m) if (a[i][j]==b[1][2]) {
		O=mk(i,j);
		a[i][j]=0;
		goto yes;
	}
	yes:;
	jin(O);
	for (;;) {
		if (n<m) rev();
		if (n==1) break;
		memset(ff,0,sizeof(ff));
		For(i,1,m) {
			PA w;
			For(j,1,n)For(k,1,m) if (!ff[j][k]&&a[j][k]==b[n][i]) {
				w=mk(j,k);
				goto jie;
			}
			jie:;
			zou(w,mk(n,i));
			ff[n][i]=1;
		}
		n--;
	}
	print();
}
int main() {
	scanf("%d%d",&n,&m);
	For(i,1,n)For(j,1,m) scanf("%d",&a[i][j]),s[a[i][j]]++;
	For(i,1,n)For(j,1,m) scanf("%d",&b[i][j]),s[b[i][j]]--;
	For(i,1,900) if (s[i]) {
		printf("-1\n");
		return 0;
	}
	if (n==1) work1(0);
	if (m==1) {
		For(i,1,n) swap(a[i][1],a[1][i]),swap(b[i][1],b[1][i]);
		swap(n,m);
		work1(1);
	}
	work();
	return 0;
}


#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <ctime>
#include <map>
#define fi first
#define se second
#define PA pair<int,int>
#define VI vector<int>
#define VP vector<PA >
#define mk(x,y) make_pair(x,y)
#define N 40
#define For(i,x,y) for (i=x;i<=y;i++)
using namespace std;
const int a1[8]={-1,-1,-1,0,0,1,1,1},a2[8]={-1,0,1,-1,1,-1,0,1};
int i,j,k,n,m,_,num;
int a[N][N],b[N][N],s[1000],ff[N][N],h[N][N];
PA O,g[N*N];
VP an,tmp;
map<PA,PA> fa;
map<PA,int> gg;
inline bool ju(int a[N],int b[N]) {
	int i;
	For(i,1,m) if (a[i]!=b[i]) return 0;
	return 1;
}
inline void print(int _,int x,int y) {
	if (_) swap(x,y);
	printf("%d %d\n",x,y);
}
inline void work1(int _) {
	For(i,1,m) {
		For(j,1,i-1) {
			int h[N];
			For(k,1,j-1) h[k]=a[1][k];
			h[j]=a[1][i];
			For(k,j,i-1) h[k+1]=a[1][k];
			For(k,i+1,m) h[k]=a[1][k];
			if (ju(h,b[1])) {
				printf("%d\n",i-j);
				for (k=i;k>=j;k--) print(_,1,k);
				exit(0);
			}
		}
		For(j,i+1,m) {
			int h[N];
			For(k,1,i-1) h[k]=a[1][k];
			For(k,i,j-1) h[k]=a[1][k+1];
			h[j]=a[1][i];
			For(k,j+1,m) h[k]=a[1][k];
			if (ju(h,b[1])) {
				printf("%d\n",j-i);
				For(k,i,j) print(_,1,k);
				exit(0);
			}
		}
	}
	printf("-1\n");
	exit(0);
}
inline void rev() {
	int i,j,c[N][N],d[N][N];
	For(i,1,n)For(j,1,m) c[j][i]=a[i][j],d[j][i]=b[i][j];
	swap(n,m);
	For(i,1,n)For(j,1,m) a[i][j]=c[i][j],b[i][j]=d[i][j];
	_^=1;
	swap(O.fi,O.se);
}
inline void jin(PA O) {
	if (_) swap(O.fi,O.se);
	an.push_back(O);
}
inline void print() {
	int i;
	printf("%d\n",an.size()-1);
	for (i=0;i<an.size();i++) printf("%d %d\n",an[i].fi,an[i].se);
}
inline void dong(PA &u) {
	jin(u);
	swap(O,u);
	swap(a[O.fi][O.se],a[u.fi][u.se]);
}
void dfs(PA O,PA now) {
	if (O==now) return;
	dfs(O,fa[now]);
	dong(now);
}
inline void bfs(PA O,PA goal) {
	int l,r,i;
	g[l=r=1]=O; gg.clear(); gg[O]=0;
	for (;l<=r;l++) {
		PA A=g[l];
		if (A==goal) {
			dfs(O,goal);
			return;
		}
		For(i,0,7) {
			int x=A.fi+a1[i],y=A.se+a2[i];
			PA u=mk(x,y);
			if (x&&y&&x<=n&&y<=m&&!ff[x][y])
				if (!gg.count(u)) {
					gg[u]=gg[A]+1; fa[u]=A; g[++r]=u;
				}
		}
	}
}
inline void gao(PA O,PA goal) {
	++num;
	tmp.clear();
	bfs(O,goal);
}
inline void zou(PA u,PA goal) {
	for (;u.se<m;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi,u.se+1));
		ff[u.fi][u.se]=0;
		dong(u);
	}
	for (;u.fi<n;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi+1,u.se));
		ff[u.fi][u.se]=0;
		dong(u);
	}
	for (;u.se>goal.se;) {
		ff[u.fi][u.se]=1;
		gao(O,mk(u.fi,u.se-1));
		ff[u.fi][u.se]=0;
		dong(u);
	}
}
inline void work() {
	For(i,1,n)For(j,1,m) if (a[i][j]==b[1][1]) {
		O=mk(i,j);
		a[i][j]=0;
		goto yes;
	}
	yes:;
	jin(O);
	for (;;) {
		if (n<m) rev();
		if (n==1) break;
		memset(ff,0,sizeof(ff));
		For(i,1,m) {
			PA w;
			For(j,1,n)For(k,1,m) if (!ff[j][k]&&a[j][k]==b[n][i]) {
				w=mk(j,k);
				goto jie;
			}
			jie:;
			zou(w,mk(n,i));
			ff[n][i]=1;
		}
		n--;
	}
	print();
}
int main() {
	//freopen("472e.in","r",stdin);
	scanf("%d%d",&n,&m);
	For(i,1,n)For(j,1,m) scanf("%d",&a[i][j]),s[a[i][j]]++;
	For(i,1,n)For(j,1,m) scanf("%d",&b[i][j]),s[b[i][j]]--;
	For(i,1,900) if (s[i]) {
		printf("-1\n");
		return 0;
	}
	if (n==1) work1(0);
	if (m==1) {
		For(i,1,n) swap(a[i][1],a[1][i]),swap(b[i][1],b[1][i]);
		swap(n,m);
		work1(1);
	}
	work();
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <ctime>
using namespace std;

const int dx[8] = {-1,-1,-1,0,0,1,1,1};
const int dy[8] = {-1,0,1,-1,1,-1,0,1};

int n,m,s[40][40],t[40][40],cnt[910],ans[1000010][2],tot;
bool v[40][40],trans;

void move(int x,int y) {
    int x1 = ans[tot - 1][0],y1 = ans[tot - 1][1];
    int x2,y2;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            if (! v[i][j] && s[i][j] == t[x][y] && !(x1 == i && y1 == j)) {
                x2 = i;
                y2 = j;
            }
    for (int dis = abs(x2 - x1) + abs(y2 - y1),tmp; dis > 1; dis = tmp) {
        int xx,yy;
        for (int i = 0; i < 8; i++) {
            xx = x1 + dx[i];
            yy = y1 + dy[i];
            tmp = abs(xx - x2) + abs(yy - y2);
            if (! v[xx][yy] && tmp < dis && ! (xx == x2 && yy == y2))
                break;
        }
        swap(s[xx][yy],s[x1][y1]);
        ans[tot][0] = x1 = xx;
        ans[tot++][1] = y1 = yy;
    }
    for (int dis = abs(x2 - x) + abs(y2 - y),tmp; ! (x2 == x && y2 == y); dis = tmp) {
        int xx,yy,tx,ty;
        for (int i = rand() % 7; ; i = rand() % 7) {
            xx = x1 + dx[i];
            yy = y1 + dy[i];
            if (xx == x2 && yy == y2) {
                tx = x1;
                ty = y1;
            }
            else {
                tx = x2;
                ty = y2;
            }
            tmp = abs(tx - x) + abs(ty - y);
            if (! v[xx][yy] && abs(xx - tx) <= 1 && abs(yy - ty) <= 1 && tmp <= dis)
                break;
        }
        swap(s[xx][yy],s[x1][y1]);
        ans[tot][0] = x1 = xx;
        ans[tot++][1] = y1 = yy;
        x2 = tx;
        y2 = ty;
    }
    v[x][y] = 1;
}

int main() {
    srand(time(0));
    scanf("%d%d",&n,&m);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) {
            scanf("%d",&s[i][j]);
            cnt[s[i][j]]++;
        }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) {
            scanf("%d",&t[i][j]);
            cnt[t[i][j]]--;
        }
    for (int i = 1; i <= 900; i++)
        if (cnt[i]) {
            printf("-1\n");
            return 0;
        }
    if (n > m) {
        trans = 1;
        for (int i = 1; i <= n; i++)
            for (int j = i + 1; j <= n; j++) {
                swap(s[i][j],s[j][i]);
                swap(t[i][j],t[j][i]);
            }
        swap(n,m);
    }
    if (n == 1) {
        int l,r;
        for (l = 1; s[1][l] == t[1][l]; l++);
        for (r = m; s[1][r] == t[1][r]; r--);
        bool flag = (s[1][l] == t[1][r]);
        for (int i = l + 1; i <= r; i++)
            flag &= (s[1][i] == t[1][i - 1]);
        if (flag) {
            printf("%d\n",r - l);
            for (int i = l; i <= r; i++) {
                int x = 1,y = i;
                if (trans)
                    swap(x,y);
                printf("%d %d\n",x,y);
            }
            return 0;
        }
        flag = (s[1][r] == t[1][l]);
        for (int i = l; i < r; i++)
            flag &= (s[1][i] == t[1][i + 1]);
        if (flag) {
            printf("%d\n",r - l);
            for (int i = r; i >= l; i--) {
                int x = 1,y = i;
                if (trans)
                    swap(x,y);
                printf("%d %d\n",x,y);
            }
            return 0;
        }
        printf("-1\n");
        return 0;
    }
    for (int i = 0; i <= n + 1; i++)
        v[i][0] = v[i][m + 1] = 1;
    for (int i = 1; i <= m; i++)
        v[0][i] = v[n + 1][i] = 1;
    for (int i = 1; i <= n && ! tot; i++)
        for (int j = 1; j <= m && ! tot; j++)
            if (s[i][j] == t[n][m]) {
                ans[tot][0] = i;
                ans[tot++][1] = j;
            }
    for (int i = 1; i < n - 1; i++)
        for (int j = 1; j <= m; j++)
            move(i,j);
    for (int i = 1; i < m; i++) {
        move(n - 1,i);
        move(n,i);
    }
    move(n - 1,m);
    printf("%d\n",tot - 1);
    for (int i = 0; i < tot; i++) {
        if (trans)
            swap(ans[i][0],ans[i][1]);
        printf("%d %d\n",ans[i][0],ans[i][1]);
    }
    return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> pii;

vector<pii> ans;
vector<pii> path;

int n, m, px, py, swaped, s[33][33], t[33][33], vis[33][33], aux[33][33], cnts[999], cntt[999];

int dx[] = {1, 1, -1, -1, 0, 1, 0, -1};
int dy[] = {1, -1, 1, -1, 1, 0, -1, 0};

void change() {
	if(m > n) return;
	swaped ^= 1;
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = s[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) s[i][j] = aux[i][j];
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = t[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) t[i][j] = aux[i][j];
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = vis[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) vis[i][j] = aux[i][j];
	swap(n, m);
}

int mod(int x) { return x > 0 ? x : -x; }

void add(int x, int y) {
	if(swaped) ans.push_back(pii(y, x));
	else ans.push_back(pii(x, y));
}

pii get(int c) {
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(!vis[i][j] && s[i][j]==c) return pii(i, j);
}

int dir(int sx, int sy, int x, int y) {
	int mi, d=1e9;
	for(int i=0;i<8;i++) {
		int nx = sx + dx[i];
		int ny = sy + dy[i];
		if(vis[nx][ny]) continue;
		int nd = mod(x-nx) + mod(y-ny);
		if(nd < d) d = nd, mi = i;
	}
	return mi;
}

void move(int x, int y) {
	while(x != px || y != py) {
		int mi = dir(px, py, x, y);
		int nx = px + dx[mi];
		int ny = py + dy[mi];
		add(nx, ny);
		swap(s[px][py], s[nx][ny]);
		swap(vis[px][py], vis[nx][ny]);
		px = nx; py = ny;
	}
}

void correct(int x, int y) {
	pii p = get(t[x][y]);
	int sx = p.first;
	int sy = p.second;
	vis[sx][sy] = 1;
	path.clear();
	path.push_back(pii(sx, sy));
	vis[px][py] = 0;
	while(sx != x || sy != y) {
		int mi = dir(sx, sy, x, y);
		sx = sx + dx[mi];
		sy = sy + dy[mi];
		path.push_back(pii(sx, sy));
	}
	vis[px][py] = 1;
	for(int i=0;i<path.size()-1;i++) {
		move(path[i+1].first, path[i+1].second);
		add(path[i].first, path[i].second);
		swap(s[px][py], s[path[i].first][path[i].second]);
		px = path[i].first;
		py = path[i].second;
	}
}

int solve() {
	for(int i=0;i<999;i++) if(cnts[i]!=cntt[i]) return 0;
	change();
	if(n==1) {
		for(int i=0;i<m;i++) for(int j=0;j<m;j++) {
			px=0, py=i;
			ans.clear();
			add(0, i);
			move(0, j);
			int k;
			for(k=0;k<m;k++) if(s[0][k] != t[0][k]) break;
			if(k==m) return 1;
			move(0, i);
		}
		return 0;
	}
	pii p = get(t[0][0]);
	px = p.first;
	py = p.second;
	vis[px][py] = 1;
	add(px, py);
	while(n > 2) {
		for(int i=0;i<m;i++) correct(n-1, i);
		n--;
		change();
	}
	move(1, 1);
	p = get(t[1][1]);
	move(p.first, p.second);
	vis[1][1]=1;
	move(1, 0);
	p = get(t[1][0]);
	move(p.first, p.second);
	move(0, 0);
	return 1;
}

int main() {
	cin>>n>>m;
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>s[i][j];
		cnts[s[i][j]]++;
	}
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>t[i][j];
		cntt[t[i][j]]++;
	}
	if(solve()) {
		cout << ans.size()-1 << endl;
		for(int i=0;i<ans.size();i++) cout << ans[i].first+1 << " " << ans[i].second+1 << endl;
	} else {
		cout << -1 << endl;
		return 0;
	}
	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> pii;

vector<pii> ans;
vector<pii> path;

int n, m, px, py, swaped, s[33][33], t[33][33], vis[33][33], aux[33][33], cnts[999], cntt[999];

int dx[] = {1, 1, -1, -1, 0, 1, 0, -1};
int dy[] = {1, -1, 1, -1, 1, 0, -1, 0};

void change() {
	if(m > n) return;
	swaped ^= 1;
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = s[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) s[i][j] = aux[i][j];
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = t[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) t[i][j] = aux[i][j];
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = vis[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) vis[i][j] = aux[i][j];
	swap(n, m);
}

int mod(int x) { return x > 0 ? x : -x; }

void add(int x, int y) {
	if(ans.size() >= 1e6) return;
	if(swaped) ans.push_back(pii(y, x));
	else ans.push_back(pii(x, y));
}

pii get(int c) {
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(!vis[i][j] && s[i][j]==c) return pii(i, j);
}

int dir(int sx, int sy, int x, int y) {
	int mi, d=1e9;
	for(int i=0;i<8;i++) {
		int nx = sx + dx[i];
		int ny = sy + dy[i];
		if(vis[nx][ny]) continue;
		int nd = mod(x-nx) + mod(y-ny);
		if(nd < d) d = nd, mi = i;
	}
	return mi;
}

void move(int x, int y) {
	while(x != px || y != py) {
		int mi = dir(px, py, x, y);
		int nx = px + dx[mi];
		int ny = py + dy[mi];
		add(nx, ny);
		swap(s[px][py], s[nx][ny]);
		swap(vis[px][py], vis[nx][ny]);
		px = nx; py = ny;
	}
}

void correct(int x, int y) {
	pii p = get(t[x][y]);
	int sx = p.first;
	int sy = p.second;
	vis[sx][sy] = 1;
	path.clear();
	path.push_back(pii(sx, sy));
	while(sx != x || sy != y) {
		int mi = dir(sx, sy, x, y);
		sx = sx + dx[mi];
		sy = sy + dy[mi];
		path.push_back(pii(sx, sy));
	}
	for(int i=0;i<path.size()-1;i++) {
		move(path[i+1].first, path[i+1].second);
		add(path[i].first, path[i].second);
		swap(s[px][py], s[path[i].first][path[i].second]);
		px = path[i].first;
		py = path[i].second;
	}
}

int solve() {
	for(int i=0;i<999;i++) if(cnts[i]!=cntt[i]) return 0;
	change();
	if(n==1) {
		for(int i=0;i<m;i++) for(int j=0;j<m;j++) {
			px=0, py=i;
			ans.clear();
			add(0, i);
			move(0, j);
			int k;
			for(k=0;k<m;k++) if(s[0][k] != t[0][k]) break;
			if(k==m) return 1;
			move(0, i);
		}
		return 0;
	}
	pii p = get(t[0][0]);
	px = p.first;
	py = p.second;
	vis[px][py] = 1;
	add(px, py);
	while(n > 2) {
		for(int i=0;i<m;i++) correct(n-1, i);
		n--;
		change();
	}
	move(1, 1);
	p = get(t[1][1]);
	move(p.first, p.second);
	vis[1][1]=1;
	move(1, 0);
	p = get(t[1][0]);
	move(p.first, p.second);
	move(0, 0);
	return 1;
}

int main() {
	cin>>n>>m;
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>s[i][j];
		cnts[s[i][j]]++;
	}
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>t[i][j];
		cntt[t[i][j]]++;
	}
	if(solve()) {
		cout << ans.size()-1 << endl;
		for(int i=0;i<ans.size();i++) cout << ans[i].first+1 << " " << ans[i].second+1 << endl;
	} else {
		cout << -1 << endl;
		return 0;
	}
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef pair<int, int> pii;
#define x first
#define y second

vector<pii> ans;

int n, m, s[33][33], t[33][33];
int ss[999], st[999];

void move(int x, int y, int nx, int ny) {
	while(x != nx || y != ny) {
		int dx = x < nx ? 1 : x > nx ? -1 : 0;
		int dy = y < ny ? 1 : y > ny ? -1 : 0;
		swap(s[x][y], s[x+dx][y+dy]);
		ans.push_back(pii(x+dx, y+dy));
		x += dx;
		y += dy;
	}
}

void correct(int x, int y) {
	if(s[x][y] == t[x][y]) return;
	int px, py;
	for(px=0;px<n;px++) {
		for(py=0;py<m;py++) if(s[px][py] != t[px][py] && ans.back() != pii(px, py) && s[px][py]==t[x][y]) break;
		if(py != m) break;
	}
	while(px != x) {
		int dx = x > px ? 1 : -1;
		int ny = py+1;
		if(py==m-1) ny=py-1;
		move(ans.back().x, ans.back().y, ans.back().x, ny);
		move(ans.back().x, ny, px+dx, ny);
		move(px+dx, ny, px+dx, py);
		move(px+dx, py, px, py);
		px += dx;
	}
	while(py != y) {
		int dy = y > py ? 1 : -1;
		int nx = px+1;
		if(px==n-1) nx=px-1;
		move(ans.back().x, ans.back().y, nx, ans.back().y);
		move(nx, ans.back().y, nx, py+dy);
		move(nx, py+dy, px, py+dy);
		move(px, py+dy, px, py);
		py += dy;
	}
}

void adjust() {
	move(ans.back().x, ans.back().y, n-1, m-1);
	if(s[n-1][m-2] == t[n-1][m-1]) move(n-1, m-1, n-1, m-2);
	else if(s[n-2][m-1] == t[n-1][m-1]) move(n-1, m-1, n-2, m-1);
	else move(n-1, m-1, n-2, m-2);

	move(ans.back().x, ans.back().y, n-2, m-1);
	if(s[n-2][m-2] == t[n-2][m-1]) {
		move(n-2, m-1, n-2, m-2);
	}
	else {
		move(n-2, m-1, n-1, m-2);
		move(n-1, m-2, n-2, m-2);
	}
}

int finished() {
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(s[i][j] != t[i][j]) return 0;
	return 1;
}

void answer() {
	cout << ans.size()-1 << endl;
	for(int i=0;i<ans.size();i++) cout << ans[i].first+1<<" "<<ans[i].second+1<<endl;
}

void debug() {
	cout << "---" << endl;
	for(int i=0;i<n;i++) {for(int j=0;j<m;j++) cout << s[i][j] << " "; cout << endl;} cout << endl;
}

int main() {
	cin>>n>>m;
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>s[i][j];
		ss[s[i][j]]++;
	}
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>t[i][j];
		st[t[i][j]]++;
	}
	for(int i=0;i<999;i++) if(ss[i] != st[i]) {
		cout << -1 << endl;
		return 0;
	}
	if(n==1 || m==1) {
		for(int x=0;x<n;x++) for(int y=0;y<m;y++)
		for(int nx=0;nx<n;nx++) for(int ny=0;ny<m;ny++) {
			ans.clear();
			ans.push_back(pii(x, y));
			move(x, y, nx, ny);
			if(finished()) {
				answer();
				return 0;
			}
			move(nx, ny, x, y);
		}
		cout << -1 << endl;
		return 0;
	}
	int px, py;
	for(px=0;px<n;px++) {
		for(py=0;py<m;py++) if(s[px][py]==t[0][0]) break;
		if(py != m) break;
	}
	ans.push_back(pii(px, py));
	move(ans.back().x, ans.back().y, 0, 0);
	while(m != 2 && n != 2) {
		move(ans.back().x, ans.back().y, 0, 0);
		if(m > n) {
			for(int i=0;i<n;i++) correct(i, m-1);
			adjust();
			m--;
		}
		else {
			for(int i=0;i<m;i++) correct(n-1, i);
			adjust();
			n--;
		}
	}
	adjust();
	answer();
	//debug();
	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> pii;

vector<pii> ans;
vector<pii> path;

int n, m, px, py, swaped, s[33][33], t[33][33], vis[33][33], aux[33][33], cnts[999], cntt[999];

int dx[] = {1, 1, -1, -1, 0, 1, 0, -1};
int dy[] = {1, -1, 1, -1, 1, 0, -1, 0};

void change() {
	if(m >= n) return;
	swaped ^= 1;
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = s[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) s[i][j] = aux[i][j];
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = t[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) t[i][j] = aux[i][j];
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = vis[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) vis[i][j] = aux[i][j];
	swap(n, m);
}

int mod(int x) { return x > 0 ? x : -x; }

void add(int x, int y) {
	if(swaped) ans.push_back(pii(y, x));
	else ans.push_back(pii(x, y));
}

pii get(int c) {
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(!vis[i][j] && s[i][j]==c) return pii(i, j);
	throw;
}

int dir(int sx, int sy, int x, int y) {
	int mi, d=1e9;
	for(int i=0;i<8;i++) {
		int nx = sx + dx[i];
		int ny = sy + dy[i];
		if(nx < 0 || nx >= n || ny < 0 || ny >= m || vis[nx][ny]) continue;
		int nd = mod(x-nx) + mod(y-ny);
		if(nd < d) d = nd, mi = i;
	}
	return mi;
}

void move(int x, int y) {
	int cnt=0;
	while(x != px || y != py) {
		if(cnt++ > 900) throw;
		int mi = dir(px, py, x, y);
		int nx = px + dx[mi];
		int ny = py + dy[mi];
		add(nx, ny);
		swap(s[px][py], s[nx][ny]);
		swap(vis[px][py], vis[nx][ny]);
		px = nx; py = ny;
	}
}

void correct(int x, int y) {
	pii p = get(t[x][y]);
	int sx = p.first;
	int sy = p.second;
	vis[sx][sy] = 1;
	path.clear();
	path.push_back(pii(sx, sy));
	vis[px][py]=0;
	int cnt=0;
	while(sx != x || sy != y) {
		if(cnt++ > 900) throw;
		int mi = dir(sx, sy, x, y);
		sx = sx + dx[mi];
		sy = sy + dy[mi];
		path.push_back(pii(sx, sy));
	}
	vis[px][py]=1;
	for(int i=0;i<path.size()-1;i++) {
		move(path[i+1].first, path[i+1].second);
		add(path[i].first, path[i].second);
		swap(s[px][py], s[path[i].first][path[i].second]);
		px = path[i].first;
		py = path[i].second;
	}
}

int solve() {
	for(int i=0;i<999;i++) if(cnts[i]!=cntt[i]) return 0;
	change();
	if(n==1) {
		for(int i=0;i<m;i++) for(int j=0;j<m;j++) {
			px=0, py=i;
			ans.clear();
			add(0, i);
			move(0, j);
			int k;
			for(k=0;k<m;k++) if(s[0][k] != t[0][k]) break;
			if(k==m) return 1;
			move(0, i);
		}
		return 0;
	}
	pii p = get(t[0][0]);
	px = p.first;
	py = p.second;
	vis[px][py] = 1;
	add(px, py);
	while(m > 2) {
		for(int i=0;i<n;i++) correct(i, m-1);
		m--;
		change();
	}
	move(1, 1);
	p = get(t[1][1]);
	move(p.first, p.second);
	vis[1][1]=1;
	move(1, 0);
	p = get(t[1][0]);
	move(p.first, p.second);
	move(0, 0);
	return 1;
}

int main() {
	cin>>n>>m;
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>s[i][j];
		cnts[s[i][j]]++;
	}
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>t[i][j];
		cntt[t[i][j]]++;
	}
	if(solve()) {
		cout << ans.size()-1 << endl;
		for(int i=0;i<ans.size();i++) cout << ans[i].first+1 << " " << ans[i].second+1 << endl;
	} else {
		cout << -1 << endl;
		return 0;
	}
	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> pii;

vector<pii> ans;
vector<pii> path;

int n, m, px, py, swaped, s[33][33], t[33][33], vis[33][33], aux[33][33], cnts[999], cntt[999];

int dx[] = {1, 1, -1, -1, 0, 1, 0, -1};
int dy[] = {1, -1, 1, -1, 1, 0, -1, 0};

void change() {
	if(m >= n) return;
	swaped ^= 1;
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = s[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) s[i][j] = aux[i][j];
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = t[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) t[i][j] = aux[i][j];
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = vis[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) vis[i][j] = aux[i][j];
	swap(n, m);
}

int mod(int x) { return x > 0 ? x : -x; }

void add(int x, int y) {
	if(swaped) ans.push_back(pii(y, x));
	else ans.push_back(pii(x, y));
}

pii get(int c) {
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(!vis[i][j] && s[i][j]==c) return pii(i, j);
}

int dir(int sx, int sy, int x, int y) {
	int mi, d=1e9;
	for(int i=0;i<8;i++) {
		int nx = sx + dx[i];
		int ny = sy + dy[i];
		if(nx < 0 || nx >= n || ny < 0 || ny >= m || vis[nx][ny]) continue;
		int nd = mod(x-nx) + mod(y-ny);
		if(nd < d) d = nd, mi = i;
	}
	return mi;
}

void move(int x, int y) {
	while(x != px || y != py) {
		int mi = dir(px, py, x, y);
		int nx = px + dx[mi];
		int ny = py + dy[mi];
		add(nx, ny);
		swap(s[px][py], s[nx][ny]);
		swap(vis[px][py], vis[nx][ny]);
		px = nx; py = ny;
	}
}

void correct(int x, int y) {
	pii p = get(t[x][y]);
	int sx = p.first;
	int sy = p.second;
	vis[sx][sy] = 1;
	path.clear();
	path.push_back(pii(sx, sy));
	vis[px][py]=0;
	while(sx != x || sy != y) {
		if(path.size() >= 1e3) break;
		int mi = dir(sx, sy, x, y);
		sx = sx + dx[mi];
		sy = sy + dy[mi];
		path.push_back(pii(sx, sy));
	}
	vis[px][py]=1;
	for(int i=0;i<path.size()-1;i++) {
		move(path[i+1].first, path[i+1].second);
		add(path[i].first, path[i].second);
		swap(s[px][py], s[path[i].first][path[i].second]);
		px = path[i].first;
		py = path[i].second;
	}
}

int solve() {
	for(int i=0;i<999;i++) if(cnts[i]!=cntt[i]) return 0;
	change();
	if(n==1) {
		for(int i=0;i<m;i++) for(int j=0;j<m;j++) {
			px=0, py=i;
			ans.clear();
			add(0, i);
			move(0, j);
			int k;
			for(k=0;k<m;k++) if(s[0][k] != t[0][k]) break;
			if(k==m) return 1;
			move(0, i);
		}
		return 0;
	}
	pii p = get(t[0][0]);
	px = p.first;
	py = p.second;
	vis[px][py] = 1;
	add(px, py);
	while(m > 2) {
		for(int i=0;i<n;i++) correct(i, m-1);
		m--;
		change();
	}
	move(1, 1);
	p = get(t[1][1]);
	move(p.first, p.second);
	vis[1][1]=1;
	move(1, 0);
	p = get(t[1][0]);
	move(p.first, p.second);
	move(0, 0);
	return 1;
}

int main() {
	cin>>n>>m;
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>s[i][j];
		cnts[s[i][j]]++;
	}
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>t[i][j];
		cntt[t[i][j]]++;
	}
	if(solve()) {
		cout << ans.size()-1 << endl;
		for(int i=0;i<ans.size();i++) cout << ans[i].first+1 << " " << ans[i].second+1 << endl;
	} else {
		cout << -1 << endl;
		return 0;
	}
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef pair<int, int> pii;
#define x first
#define y second

vector<pii> ans;

int n, m, N, M, s[33][33], t[33][33];
int ss[999], st[999];

void move(int x, int y, int nx, int ny) {
	while(x != nx || y != ny) {
		int dx = x < nx ? 1 : x > nx ? -1 : 0;
		int dy = y < ny ? 1 : y > ny ? -1 : 0;
		swap(s[x][y], s[x+dx][y+dy]);
		ans.push_back(pii(x+dx, y+dy));
		x += dx;
		y += dy;
	}
}

void correcty(int x, int y) {
	if(s[x][y] == t[x][y]) return;
	int px, py;
	for(px=0;px<n;px++) {
		for(py=0;py<m;py++) if(s[px][py] != t[px][py] && ans.back() != pii(px, py) && s[px][py]==t[x][y]) break;
		if(py != m) break;
	}
	while(py != y) {
		int dy = y > py ? 1 : -1;
		int nx = px+1;
		if(px==n-1) nx=px-1;
		move(ans.back().x, ans.back().y, nx, ans.back().y);
		move(nx, ans.back().y, nx, py+dy);
		move(nx, py+dy, px, py+dy);
		move(px, py+dy, px, py);
		py += dy;
	}
	while(px != x) {
		int dx = x > px ? 1 : -1;
		int ny = py+1;
		if(py==m-1) ny=py-1;
		move(ans.back().x, ans.back().y, ans.back().x, ny);
		move(ans.back().x, ny, px+dx, ny);
		move(px+dx, ny, px+dx, py);
		move(px+dx, py, px, py);
		px += dx;
	}
}

void correctx(int x, int y) {
	if(s[x][y] == t[x][y]) return;
	int px, py;
	for(px=0;px<n;px++) {
		for(py=0;py<m;py++) if(s[px][py] != t[px][py] && ans.back() != pii(px, py) && s[px][py]==t[x][y]) break;
		if(py != m) break;
	}
	while(px != x) {
		int dx = x > px ? 1 : -1;
		int ny = py+1;
		if(py==m-1) ny=py-1;
		move(ans.back().x, ans.back().y, ans.back().x, ny);
		move(ans.back().x, ny, px+dx, ny);
		move(px+dx, ny, px+dx, py);
		move(px+dx, py, px, py);
		px += dx;
	}
	while(py != y) {
		int dy = y > py ? 1 : -1;
		int nx = px+1;
		if(px==n-1) nx=px-1;
		move(ans.back().x, ans.back().y, nx, ans.back().y);
		move(nx, ans.back().y, nx, py+dy);
		move(nx, py+dy, px, py+dy);
		move(px, py+dy, px, py);
		py += dy;
	}
}

void adjust() {
	move(ans.back().x, ans.back().y, n-1, m-1);
	if(s[n-1][m-2] == t[n-1][m-1]) move(n-1, m-1, n-1, m-2);
	else if(s[n-2][m-1] == t[n-1][m-1]) move(n-1, m-1, n-2, m-1);
	else move(n-1, m-1, n-2, m-2);

	move(ans.back().x, ans.back().y, n-2, m-1);
	if(s[n-2][m-2] == t[n-2][m-1]) {
		move(n-2, m-1, n-2, m-2);
	}
	else {
		move(n-2, m-1, n-1, m-2);
		move(n-1, m-2, n-2, m-2);
	}
}

int finished() {
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(s[i][j] != t[i][j]) return 0;
	return 1;
}

void answer() {
	cout << ans.size()-1 << endl;
	for(int i=0;i<ans.size();i++) cout << ans[i].first+1<<" "<<ans[i].second+1<<endl;
}

void debug() {
	cout << "---" << endl;
	for(int i=0;i<N;i++) {for(int j=0;j<M;j++) cout << s[i][j] << " "; cout << endl;} cout << endl;
}

int main() {
	cin>>n>>m;
	N=n, M=m;
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>s[i][j];
		ss[s[i][j]]++;
	}
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>t[i][j];
		st[t[i][j]]++;
	}
	for(int i=0;i<999;i++) if(ss[i] != st[i]) {
		cout << -1 << endl;
		return 0;
	}
	if(n==1 || m==1) {
		for(int x=0;x<n;x++) for(int y=0;y<m;y++)
		for(int nx=0;nx<n;nx++) for(int ny=0;ny<m;ny++) {
			ans.clear();
			ans.push_back(pii(x, y));
			move(x, y, nx, ny);
			if(finished()) {
				answer();
				return 0;
			}
			move(nx, ny, x, y);
		}
		cout << -1 << endl;
		return 0;
	}
	int px, py;
	for(px=0;px<n;px++) {
		for(py=0;py<m;py++) if(s[px][py]==t[0][0]) break;
		if(py != m) break;
	}
	ans.push_back(pii(px, py));
	move(ans.back().x, ans.back().y, 0, 0);
	while(m != 2 || n != 2) {
		move(ans.back().x, ans.back().y, 0, 0);
		if(m > n) {
			for(int i=0;i<n;i++) correctx(i, m-1);
			adjust();
			m--;
		}
		else {
			for(int i=0;i<m;i++) correcty(n-1, i);
			adjust();
			n--;
		}
	}
	adjust();
	answer();
	//debug();
	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> pii;

vector<pii> ans;
vector<pii> path;

int n, m, px, py, swaped, s[33][33], t[33][33], vis[33][33], aux[33][33], cnts[999], cntt[999];

int dx[] = {1, 1, -1, -1, 0, 1, 0, -1};
int dy[] = {1, -1, 1, -1, 1, 0, -1, 0};

void change() {
	if(m >= n) return;
	swaped ^= 1;
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = s[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) s[i][j] = aux[i][j];
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = t[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) t[i][j] = aux[i][j];
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = vis[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) vis[i][j] = aux[i][j];
	swap(n, m);
}

int mod(int x) { return x > 0 ? x : -x; }

void add(int x, int y) {
	if(swaped) ans.push_back(pii(y, x));
	else ans.push_back(pii(x, y));
}

pii get(int c) {
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(!vis[i][j] && s[i][j]==c) return pii(i, j);
	throw;
}

int dir(int sx, int sy, int x, int y) {
	int mi, d=1e9;
	for(int i=0;i<8;i++) {
		int nx = sx + dx[i];
		int ny = sy + dy[i];
		if(nx < 0 || nx >= n || ny < 0 || ny >= m || vis[nx][ny]) continue;
		int nd = mod(x-nx) + mod(y-ny);
		if(nd < d) d = nd, mi = i;
	}
	return mi;
}

void move(int x, int y) {
	int cnt=0;
	while(x != px || y != py) {
		if(cnt++ > 900) throw;
		int mi = dir(px, py, x, y);
		int nx = px + dx[mi];
		int ny = py + dy[mi];
		add(nx, ny);
		swap(s[px][py], s[nx][ny]);
		swap(vis[px][py], vis[nx][ny]);
		px = nx; py = ny;
	}
}

void correct(int x, int y) {
	pii p = get(t[x][y]);
	int sx = p.first;
	int sy = p.second;
	vis[sx][sy] = 1;
	path.clear();
	path.push_back(pii(sx, sy));
	vis[px][py]=0;
	while(sx != x || sy != y) {
		int mi = dir(sx, sy, x, y);
		sx = sx + dx[mi];
		sy = sy + dy[mi];
		path.push_back(pii(sx, sy));
	}
	vis[px][py]=1;
	for(int i=0;i<path.size()-1;i++) {
		move(path[i+1].first, path[i+1].second);
		add(path[i].first, path[i].second);
		swap(s[px][py], s[path[i].first][path[i].second]);
		px = path[i].first;
		py = path[i].second;
	}
}

int solve() {
	for(int i=0;i<999;i++) if(cnts[i]!=cntt[i]) return 0;
	change();
	if(n==1) {
		for(int i=0;i<m;i++) for(int j=0;j<m;j++) {
			px=0, py=i;
			ans.clear();
			add(0, i);
			move(0, j);
			int k;
			for(k=0;k<m;k++) if(s[0][k] != t[0][k]) break;
			if(k==m) return 1;
			move(0, i);
		}
		return 0;
	}
	pii p = get(t[0][0]);
	px = p.first;
	py = p.second;
	vis[px][py] = 1;
	add(px, py);
	while(m > 2) {
		for(int i=0;i<n;i++) correct(i, m-1);
		m--;
		change();
	}
	move(1, 1);
	p = get(t[1][1]);
	move(p.first, p.second);
	vis[1][1]=1;
	move(1, 0);
	p = get(t[1][0]);
	move(p.first, p.second);
	move(0, 0);
	return 1;
}

int main() {
	cin>>n>>m;
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>s[i][j];
		cnts[s[i][j]]++;
	}
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>t[i][j];
		cntt[t[i][j]]++;
	}
	if(solve()) {
		cout << ans.size()-1 << endl;
		for(int i=0;i<ans.size();i++) cout << ans[i].first+1 << " " << ans[i].second+1 << endl;
	} else {
		cout << -1 << endl;
		return 0;
	}
	return 0;
}


#include<cstdio>
#include<cstring>
#define db double
#include<algorithm>
#include<iostream>
#define ll long long
using namespace std;
inline void rd(int &res){
    res=0;char c;int k=1;
    while(c=getchar(),c<48&&c!='-');
    if(c=='-'){k=-1;c=getchar();}
    do res=(res<<1)+(res<<3)+(c^48);
    while(c=getchar(),c>=48);res*=k;
}
void print(ll x){
    if(!x)return ;
    print(x/10);
    putchar((x%10)^48);
}
void sc(ll x){
    if(x<0){x=-x;putchar('-');}
    print(x);
    if(!x)putchar('0');
    putchar('\n');
}
const int M=3e5+5;//用左边的插入去更新右边的询问
struct node{
    int op,a,b;
}q[M];
db f[M],eps=1e-9;
ll res[M],oo=3e18+7e17;
int n,top,m,Q[M],A[M],en[M];

bool cmp(int a,int b){
    if(q[a].a!=q[b].a)return q[a].a<q[b].a;
    return q[a].b<q[b].b;
}
db chk(int a,int b){
    if(q[a].a==q[b].a)return -oo;
    return (db)(q[b].b-q[a].b)/(q[a].a-q[b].a);
}
void build(){
    int i,j;
    sort(A+1,A+1+m,cmp);
    f[A[1]]=-oo;
    for(i=1;i<=m;i++){
        while(top&&(f[A[i]]=chk(A[i],Q[top]))<=f[Q[top]])top--;
        Q[++top]=A[i];
    	if(top>1)f[A[i]]=chk(A[i],Q[top-1]);
        else f[A[i]]=-oo;
    }
}
ll find(int v){
    int res=0,l=1,r=top;
    while(l<=r){
        int mid=l+r>>1;
        if(f[Q[mid]]<=v){
            res=Q[mid];
            l=mid+1;
        }else r=mid-1;
    }
    if(res)return ((ll)q[res].a*v+q[res].b);
    return -oo;
}
void solve(int L,int R){
    if(L==R)return ;
    int mid=L+R>>1,i,j,k;

    top=m=0;
    for(i=L;i<=mid;i++)if(!q[i].op&&en[i]>R)A[++m]=i;
    build();
//    printf("%d %d %d %d\n",L,R,m,top);
    for(i=mid+1;i<=R;i++){
		if(q[i].op==1){
			res[i]=max(res[i],find(q[i].a));
//    		printf("%d %d %lld\n",top,i,res[i]);
		}
	}
	top=m=0;
    for(i=mid+1;i<=R;i++)if(q[i].op==2&&q[i].a<L)A[++m]=q[i].a;
    build();
    for(i=L;i<=mid;i++)if(q[i].op==1)res[i]=max(res[i],find(q[i].a));

	solve(L,mid);
    solve(mid+1,R);
}
int main(){
//  freopen("da.in","r",stdin);
//  	freopen("my.out","w",stdout);
    rd(n);
    int i;
    for(i=1;i<=n;i++){
    	res[i]=-oo;
        rd(q[i].op);rd(q[i].a);

        if(q[i].op==1)q[i].op=0;
        else if(q[i].op==3)q[i].op=1;

        if(q[i].op==0)rd(q[i].b);
    	else if(q[i].op==2)en[q[i].a]=i;
	}
	for(i=1;i<=n;i++){
		if(!q[i].op&&!en[i])en[i]=n+1;
	}
    solve(1,n);
    for(i=1;i<=n;i++){
		if(q[i].op==1){
			if(res[i]!=-oo)sc(res[i]);
    		else puts("EMPTY SET");
		}
	}
	return 0;
}


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

#define mp make_pair
#define pb push_back

typedef long long ll;
typedef pair<int, int> pii;

const int BLOCK = 2500;
const int MAXN = 300100;

struct Line {
  int k, b;
  int id;
  Line(int k, int b, int id) : k(k), b(b), id(id) {}
  bool operator<(Line l) const {
    if (k != l.k) return k < l.k;
    if (b != l.b) return b < l.b;
    return id < l.id;
  }
};
struct Query {
  int t, a, b;
  Query(int t = 0, int a = 0, int b = 0) : t(t), a(a), b(b) {}
};
set<Line> lines, blockLines;
vector<Query> qs;
int n;
ll ans[MAXN];

bool needPop(vector<Line> &st, Line l3) {
  if (st.size() < 2) return false;
  Line l1 = st[(int)st.size() - 2];
  Line l2 = st[(int)st.size() - 1];
  return (l2.b - l3.b) * 1ll * (l2.k - l1.k) <= (l1.b - l2.b) * 1ll * (l3.k - l2.k);
}

int main() {
#ifdef LOCAL
  freopen("input.txt", "r", stdin);
#endif
  double start = clock();
  scanf("%d", &n);
  qs.resize(n);
  for (int i = 0; i < n; ++i) {
    scanf("%d", &qs[i].t);
    if (qs[i].t == 1) {
      scanf("%d%d", &qs[i].a, &qs[i].b);
    } else {
      scanf("%d", &qs[i].a);
    }
  }
  fill(ans, ans + n, LLONG_MIN);
  for (int i = 0; i < n; i += BLOCK) {
    int l = i;
    int r = min(n, i + BLOCK);
    vector<pii> xs;
    for (int j = l; j < r; ++j) {
      if (qs[j].t == 2) {
        lines.erase(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
      } else if (qs[j].t == 3) {
        xs.pb(mp(qs[j].a, j));
      }
    }
    vector<Line> st;
    for (auto it : lines) {
      while (needPop(st, it)) st.pop_back();
      st.pb(it);
    }
    sort(xs.begin(), xs.end());
    int it = 0;
    for (auto x : xs) {
      while (it + 1 < (int)st.size() && (st[it].b - st[it + 1].b < x.first * 1ll * (st[it + 1].k - st[it].k)))
        ++it;
      if (it < (int)st.size())
        ans[x.second] = max(ans[x.second], st[it].k * 1ll * x.first + st[it].b);
    }
    blockLines.clear();
    for (int j = l; j < r; ++j) {
      if (qs[j].t == 1) blockLines.insert(Line(qs[j].a, qs[j].b, j));
      else if (qs[j].t == 2) blockLines.erase(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
    }
    for (int j = r - 1; j >= l; --j) {
      if (qs[j].t == 1) {
        blockLines.erase(Line(qs[j].a, qs[j].b, j));
      } else if (qs[j].t == 2) {
        blockLines.insert(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
      } else {
        for (auto it : blockLines) {
          ans[j] = max(ans[j], qs[j].a * 1ll * it.k + it.b);
        }
      }
    }
    for (int j = l; j < r; ++j) {
      if (qs[j].t == 1) {
        lines.insert(Line(qs[j].a, qs[j].b, j));
      } else if (qs[j].t == 2) {
        lines.erase(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
      }
    }
  }
  for (int i = 0; i < n; ++i) {
    if (qs[i].t == 3) {
      if (ans[i] == LLONG_MIN) puts("EMPTY SET");
      else printf("%lld\n", ans[i]);
    }
  }
  clog << (clock() - start) / CLOCKS_PER_SEC << endl;
  return 0;
}


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

#define mp make_pair
#define pb push_back

typedef long long ll;
typedef pair<int, int> pii;

const int BLOCK = 550;
const int MAXN = 300100;

struct Line {
  int k, b;
  int id;
  Line(int k, int b, int id) : k(k), b(b), id(id) {}
  bool operator<(Line l) const {
    if (k != l.k) return k < l.k;
    if (b != l.b) return b < l.b;
    return id < l.id;
  }
};
struct Query {
  int t, a, b;
  Query(int t = 0, int a = 0, int b = 0) : t(t), a(a), b(b) {}
};
set<Line> lines, blockLines;
vector<Query> qs;
int n;
ll ans[MAXN];

bool needPop(vector<Line> &st, Line l3) {
  if (st.size() < 2) return false;
  Line l1 = st[(int)st.size() - 2];
  Line l2 = st[(int)st.size() - 1];
  return (l2.b - l3.b) * 1ll * (l2.k - l1.k) <= (l1.b - l2.b) * 1ll * (l3.k - l2.k);
}

int main() {
#ifdef LOCAL
  freopen("input.txt", "r", stdin);
#endif
  scanf("%d", &n);
  qs.resize(n);
  for (int i = 0; i < n; ++i) {
    scanf("%d", &qs[i].t);
    if (qs[i].t == 1) {
      scanf("%d%d", &qs[i].a, &qs[i].b);
    } else {
      scanf("%d", &qs[i].a);
    }
  }
  fill(ans, ans + n, LLONG_MIN);
  for (int i = 0; i < n; i += BLOCK) {
    int l = i;
    int r = min(n, i + BLOCK);
    vector<pii> xs;
    for (int j = l; j < r; ++j) {
      if (qs[j].t == 2) {
        lines.erase(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
      } else if (qs[j].t == 3) {
        xs.pb(mp(qs[j].a, j));
      }
    }
    vector<Line> st;
    for (auto it : lines) {
      while (needPop(st, it)) st.pop_back();
      st.pb(it);
    }
    sort(xs.begin(), xs.end());
    int it = 0;
    for (auto x : xs) {
      while (it + 1 < (int)st.size() && (st[it].b - st[it + 1].b < x.first * 1ll * (st[it + 1].k - st[it].k)))
        ++it;
      if (it < (int)st.size())
        ans[x.second] = max(ans[x.second], st[it].k * 1ll * x.first + st[it].b);
    }
    blockLines.clear();
    for (int j = l; j < r; ++j) {
      if (qs[j].t == 1) blockLines.insert(Line(qs[j].a, qs[j].b, j));
      else if (qs[j].t == 2) blockLines.erase(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
    }
    for (int j = r - 1; j >= l; --j) {
      if (qs[j].t == 1) {
        blockLines.erase(Line(qs[j].a, qs[j].b, j));
      } else if (qs[j].t == 2) {
        blockLines.insert(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
      } else {
        for (auto it : blockLines) {
          ans[j] = max(ans[j], qs[j].a * 1ll * it.k + it.b);
        }
      }
    }
    for (int j = l; j < r; ++j) {
      if (qs[j].t == 1) {
        lines.insert(Line(qs[j].a, qs[j].b, j));
      } else if (qs[j].t == 2) {
        lines.erase(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
      }
    }
  }
  for (int i = 0; i < n; ++i) {
    if (qs[i].t == 3) {
      if (ans[i] == LLONG_MIN) puts("EMPTY SET");
      else printf("%lld\n", ans[i]);
    }
  }
  return 0;
}


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

#define mp make_pair
#define pb push_back

typedef long long ll;
typedef pair<int, int> pii;

const int BLOCK = 2000;
const int MAXN = 300100;

struct Line {
  int k, b;
  int id;
  Line(int k, int b, int id) : k(k), b(b), id(id) {}
  bool operator<(Line l) const {
    if (k != l.k) return k < l.k;
    if (b != l.b) return b < l.b;
    return id < l.id;
  }
};
struct Query {
  int t, a, b;
  Query(int t = 0, int a = 0, int b = 0) : t(t), a(a), b(b) {}
};
set<Line> lines, blockLines;
vector<Query> qs;
int n;
ll ans[MAXN];

bool needPop(vector<Line> &st, Line l3) {
  if (st.size() < 2) return false;
  Line l1 = st[(int)st.size() - 2];
  Line l2 = st[(int)st.size() - 1];
  return (l2.b - l3.b) * 1ll * (l2.k - l1.k) <= (l1.b - l2.b) * 1ll * (l3.k - l2.k);
}

int main() {
#ifdef LOCAL
  freopen("input.txt", "r", stdin);
#endif
  double start = clock();
  scanf("%d", &n);
  qs.resize(n);
  for (int i = 0; i < n; ++i) {
    scanf("%d", &qs[i].t);
    if (qs[i].t == 1) {
      scanf("%d%d", &qs[i].a, &qs[i].b);
    } else {
      scanf("%d", &qs[i].a);
    }
  }
  fill(ans, ans + n, LLONG_MIN);
  for (int i = 0; i < n; i += BLOCK) {
    int l = i;
    int r = min(n, i + BLOCK);
    vector<pii> xs;
    for (int j = l; j < r; ++j) {
      if (qs[j].t == 2) {
        lines.erase(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
      } else if (qs[j].t == 3) {
        xs.pb(mp(qs[j].a, j));
      }
    }
    vector<Line> st;
    for (auto it : lines) {
      while (needPop(st, it)) st.pop_back();
      st.pb(it);
    }
    sort(xs.begin(), xs.end());
    int it = 0;
    for (auto x : xs) {
      while (it + 1 < (int)st.size() && (st[it].b - st[it + 1].b < x.first * 1ll * (st[it + 1].k - st[it].k)))
        ++it;
      if (it < (int)st.size())
        ans[x.second] = max(ans[x.second], st[it].k * 1ll * x.first + st[it].b);
    }
    blockLines.clear();
    for (int j = l; j < r; ++j) {
      if (qs[j].t == 1) blockLines.insert(Line(qs[j].a, qs[j].b, j));
      else if (qs[j].t == 2) blockLines.erase(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
    }
    for (int j = r - 1; j >= l; --j) {
      if (qs[j].t == 1) {
        blockLines.erase(Line(qs[j].a, qs[j].b, j));
      } else if (qs[j].t == 2) {
        blockLines.insert(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
      } else {
        for (auto it : blockLines) {
          ans[j] = max(ans[j], qs[j].a * 1ll * it.k + it.b);
        }
      }
    }
    for (int j = l; j < r; ++j) {
      if (qs[j].t == 1) {
        lines.insert(Line(qs[j].a, qs[j].b, j));
      } else if (qs[j].t == 2) {
        lines.erase(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
      }
    }
  }
  for (int i = 0; i < n; ++i) {
    if (qs[i].t == 3) {
      if (ans[i] == LLONG_MIN) puts("EMPTY SET");
      else printf("%lld\n", ans[i]);
    }
  }
  clog << (clock() - start) / CLOCKS_PER_SEC << endl;
  return 0;
}


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

#define pb push_back
#define mp make_pair

typedef long long ll;
typedef pair<int, int> pii;

const int MAXN = 1 << 19;

struct Line {
  int k, b;
  Line(int k, int b) : k(k), b(b) {}
  bool operator<(Line l) const {
    if (k != l.k) return k < l.k;
    return b < l.b;
  }
};

vector<Line> t[2 * MAXN];
int n;
bool alive[MAXN];
int cmd[MAXN];
int a[MAXN], b[MAXN];

void add(int v, int tl, int tr, int l, int r, Line L) {
  if (l >= r) return;
  if (tl == l && tr == r) {
    return t[v].pb(L);
  }
  int tm = (tl + tr) >> 1;
  add(v << 1, tl, tm, l, min(r, tm), L);
  add(v << 1 | 1, tm, tr, max(l, tm), r, L);
}
void add(int l, int r, Line L) {
  add(1, 0, MAXN, l, r, L);
}

bool needPop(vector<Line> &st, Line l3) {
  if ((int)st.size() < 2) return false;
  Line l1 = st[(int)st.size() - 2];
  Line l2 = st[(int)st.size() - 1];
  return (l2.b - l3.b) * 1ll * (l2.k - l1.k) <= (l1.b - l2.b) * 1ll * (l3.k - l2.k);
}

void build() {
  for (int i = 2 * MAXN - 1; i > 0; --i) {
    sort(t[i].begin(), t[i].end());
    vector<Line> st;
    for (int j = 0; j < (int)t[i].size(); ++j) {
      while (needPop(st, t[i][j])) st.pop_back();
      st.pb(t[i][j]);
    }
    t[i] = st;
  }
}

ll f(vector<Line> &line, ll q) {
  if (line.empty()) return LLONG_MIN;
  int l = 0;
  int r = line.size();
  while (r - l > 1) {
    int mid = (r + l) >> 1;
    if ((line[mid].k - line[mid - 1].k) * q > line[mid - 1].b - line[mid].b)
      l = mid;
    else r = mid;
  }
  return line[l].k * q + line[l].b;
}

ll get(int v, int q) {
  v += MAXN;
  ll res = LLONG_MIN;
  while (v) {
    res = max(res, f(t[v], q));
    v >>= 1;
  }
  return res;
}

int main() {
#ifdef LOCAL
  freopen("input.txt", "r", stdin);
#endif
  scanf("%d", &n);
  for (int i = 0; i < n; ++i) {
    scanf("%d%d", cmd + i, a + i);
    if (cmd[i] == 1) {
      scanf("%d", b + i);
      alive[i] = true;
    } else if (cmd[i] == 2) {
      add(a[i] - 1, i, Line(a[a[i] - 1], b[a[i] - 1]));
      alive[a[i] - 1] = false;
    }
  }
  for (int i = 0; i < n; ++i) {
    if (alive[i]) {
      add(i, n, Line(a[i], b[i]));
    }
  }
  build();
  for (int i = 0; i < n; ++i) {
    if (cmd[i] == 3) {
      ll res = get(i, a[i]);
      if (res == LLONG_MIN) puts("EMPTY SET");
      else printf("%lld\n", res);
    }
  }
  return 0;
}


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

#define mp make_pair
#define pb push_back

typedef long long ll;
typedef pair<int, int> pii;

const int BLOCK = 550;
const int MAXN = 300100;

struct Line {
  int k, b;
  int id;
  Line(int k, int b, int id) : k(k), b(b), id(id) {}
  bool operator<(Line l) const {
    if (k != l.k) return k < l.k;
    if (b != l.b) return b < l.b;
    return id < l.id;
  }
};
struct Query {
  int t, a, b;
  Query(int t = 0, int a = 0, int b = 0) : t(t), a(a), b(b) {}
};
set<Line> lines, blockLines;
vector<Query> qs;
int n;
ll ans[MAXN];

bool needPop(vector<Line> &st, Line l3) {
  if (st.size() < 2) return false;
  Line l1 = st[(int)st.size() - 2];
  Line l2 = st[(int)st.size() - 1];
  return (l2.b - l3.b) * 1ll * (l2.k - l1.k) <= (l1.b - l2.b) * 1ll * (l3.k - l2.k);
}

int main() {
#ifdef LOCAL
  freopen("input.txt", "r", stdin);
#endif
  scanf("%d", &n);
  qs.resize(n);
  for (int i = 0; i < n; ++i) {
    scanf("%d", &qs[i].t);
    if (qs[i].t == 1) {
      scanf("%d%d", &qs[i].a, &qs[i].b);
    } else {
      scanf("%d", &qs[i].a);
    }
  }
  fill(ans, ans + n, LLONG_MIN);
  for (int i = 0; i < n; i += BLOCK) {
    int l = i;
    int r = min(n, i + BLOCK);
    vector<pii> xs;
    for (int j = l; j < r; ++j) {
      if (qs[j].t == 2) {
        lines.erase(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
      } else if (qs[j].t == 3) {
        xs.pb(mp(qs[j].a, j));
      }
    }
    vector<Line> st;
    for (auto it : lines) {
      while (needPop(st, it)) st.pop_back();
      st.pb(it);
    }
    sort(xs.begin(), xs.end());
    int it = 0;
    for (auto x : xs) {
      while (it + 1 < (int)st.size() && (st[it].b - st[it + 1].b < x.first * 1ll * (st[it + 1].k - st[it].k)))
        ++it;
      if (it < (int)st.size())
        ans[x.second] = max(ans[x.second], st[it].k * 1ll * x.first + st[it].b);
    }
    blockLines.clear();
    for (int j = l; j < r; ++j) {
      if (qs[j].t == 1) blockLines.insert(Line(qs[j].a, qs[j].b, j));
      else if (qs[j].t == 2) blockLines.erase(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
    }
    for (int j = r - 1; j >= l; --j) {
      if (qs[j].t == 1) {
        blockLines.erase(Line(qs[j].a, qs[j].b, j));
      } else if (qs[j].t == 2) {
        blockLines.insert(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
      } else {
        for (auto it : blockLines) {
          ans[j] = max(ans[j], qs[j].a * 1ll * it.k + it.b);
        }
      }
    }
    for (int j = l; j < r; ++j) {
      if (qs[j].t == 1) {
        lines.insert(Line(qs[j].a, qs[j].b, j));
      } else {
        lines.erase(Line(qs[qs[j].a - 1].a, qs[qs[j].a - 1].b, qs[j].a - 1));
      }
    }
  }
  for (int i = 0; i < n; ++i) {
    if (qs[i].t == 3) {
      if (ans[i] == LLONG_MIN) puts("EMPTY SET");
      else printf("%lld\n", ans[i]);
    }
  }
  return 0;
}


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

#define pb push_back
#define mp make_pair
#define k first
#define b second

typedef long long ll;
typedef pair<int, int> Line;

const int MAXN = 1 << 19;

vector<Line> t[2 * MAXN];
int n;
bool alive[MAXN];
int cmd[MAXN];
int a[MAXN], b[MAXN];

void add(int v, int tl, int tr, int l, int r, Line L) {
  if (l >= r) return;
  if (tl == l && tr == r) {
    return t[v].pb(L);
  }
  int tm = (tl + tr) >> 1;
  add(v << 1, tl, tm, l, min(r, tm), L);
  add(v << 1 | 1, tm, tr, max(l, tm), r, L);
}
void add(int l, int r, Line L) {
  add(1, 0, MAXN, l, r, L);
}

bool needPop(vector<Line> &st, Line l3) {
  if ((int)st.size() < 2) return false;
  Line l1 = st[(int)st.size() - 2];
  Line l2 = st[(int)st.size() - 1];
  return (ll)(l2.b - l3.b) * (l2.k - l1.k) <= (ll)(l1.b - l2.b) * (l3.k - l2.k);
}

void build() {
  for (int i = 2 * MAXN - 1; i > 0; --i) {
    sort(t[i].begin(), t[i].end());
    vector<Line> st;
    for (int j = 0; j < (int)t[i].size(); ++j) {
      while (needPop(st, t[i][j])) st.pop_back();
      st.pb(t[i][j]);
    }
    t[i] = st;
  }
}

ll f(vector<Line> &line, ll q) {
  if (line.empty()) return LLONG_MIN;
  int l = 0;
  int r = line.size();
  while (r - l > 1) {
    int mid = (r + l) >> 1;
    if ((line[mid].k - line[mid - 1].k) * q > line[mid - 1].b - line[mid].b)
      l = mid;
    else r = mid;
  }
  return line[l].k * q + line[l].b;
}

ll get(int v, int q) {
  v += MAXN;
  ll res = LLONG_MIN;
  while (v) {
    res = max(res, f(t[v], q));
    v >>= 1;
  }
  return res;
}

int main() {
#ifdef LOCAL
  freopen("input.txt", "r", stdin);
#endif
  scanf("%d", &n);
  for (int i = 0; i < n; ++i) {
    scanf("%d%d", cmd + i, a + i);
    if (cmd[i] == 1) {
      scanf("%d", b + i);
      alive[i] = true;
    } else if (cmd[i] == 2) {
      add(a[i] - 1, i, Line(a[a[i] - 1], b[a[i] - 1]));
      alive[a[i] - 1] = false;
    }
  }
  for (int i = 0; i < n; ++i) {
    if (alive[i]) {
      add(i, n, Line(a[i], b[i]));
    }
  }
  build();
  for (int i = 0; i < n; ++i) {
    if (cmd[i] == 3) {
      ll res = get(i, a[i]);
      if (res == LLONG_MIN) puts("EMPTY SET");
      else printf("%lld\n", res);
    }
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
ll ans[maxn];
int r[maxn];

inline int getID(int l,int r){
	return (l+r)|(l<r);
}

struct Point{
	ll x,y;
	Point(ll x,ll y):x(x),y(y){
	}
	Point(){
	}
	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

Point ch[maxn];
vector<Point> pts[maxn<<1];

void update(int tl,int tr,int l,int r,Point pt){
	if(l == tl && r == tr){
		pts[getID(l,r)].push_back(pt);
		return;
	}
	int mid = (tl+tr)>>1;
	if(r <= mid){
		update(tl,mid,l,r,pt);
	}else{
		if(l > mid){
			update(mid+1,tr,l,r,pt);
		}else{
			update(tl,mid,l,mid,pt);
			update(mid+1,tr,mid+1,r,pt);
		}
	}
}

int sz;	//ConvexHull's size

int n;

void ConvexHull(int id){
	sort(pts[id].begin(),pts[id].end());
	sz = 0;
	Point pre = Point(-INF,-INF);
	for(int i=0;i<(int)pts[id].size();i++){
		Point pt = pts[id][i];
		if(pt.x == pre.x){
			continue;
		}
		pre = pt;
		if(sz<2){
			ch[sz++] = pt;
		}else{
			while(sz>=2 && (pt.y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
					(ch[sz-1].y-ch[sz-2].y)*(pt.x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pt;
		}
	}
}

inline ll calc(int ptid,int qid){
	return ch[ptid].y+ch[ptid].x*a[qid];
}

ll bs(int l,int r,int qid){
	int L = l;
	int R = r;
	ll res = -INF;
	while(l<=r){
		int mid = (l+r)>>1;
		ll mval = calc(mid,qid);
		res = max(res,mval);
		if(mid > L && calc(mid-1,qid) > mval){
			r = mid-1;
		}else if(mid < R && calc(mid+1,qid) > mval){
			l = mid+1;
		}else{
			break;
		}
	}
	return res;
}

void cdq(int l,int r){
	int mid = (l+r)>>1;

	if(l<r)cdq(l,mid);
	if(l<r)cdq(mid+1,r);

	ConvexHull(getID(l,r));
	for(int i=l;i<=r;i++){
		if(t[i] == 3){
			ans[i] = max(ans[i],bs(0,sz-1,i));
		}
	}
}

int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
			r[i] = n;
		}else{
			scanf("%I64d",&a[i]);
			if(t[i] == 2){
				r[a[i]] = i-1;
			}
		}
		ans[i] = -INF;
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 1){
			update(1,n,i+1,r[i],Point(a[i],b[i]));
		}
	}

	cdq(1,n);

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			if(ans[i] == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",ans[i]);
			}
		}
	}
	return 0;
}