#include <bits/stdc++.h>
using namespace std;
const int MAXN = 120 * 1000;
const int MAXK = 13;
int n, q, k;
int x[MAXK][MAXN];
int sorted_x[MAXK][MAXN];
bitset<MAXN * MAXK> big_bitset[MAXK];
bitset<(1 << MAXK)> small_bitset[MAXN + MAXK];
int match[MAXN * MAXK];
void fill_small() {
  int len = 0;
  int was[1 << MAXK];
  memset(was, -1, sizeof was);
  for (int i = 0; i < MAXN * MAXK; i++) {
    int cur = 0;
    for (int j = 0; j < k; j++) {
      cur <<= 1;
      cur += big_bitset[j][i];
    }
    if (was[cur] == -1) {
      was[cur] = len;
      for (int j = 0; j < k; j++) {
        small_bitset[j][len] = big_bitset[j][i];
      }
      len++;
    }
    match[i] = was[cur];
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> k >> q;
  for (int i = 0; i < k; i++)
    for (int j = 0; j < n; j++) {
      cin >> x[i][j];
    }
  {
    int len = 0;
    for (int j = 0; j < n; j++) {
      int buf_x[MAXK];
      for (int i = 0; i < k; i++) buf_x[i] = x[i][j];
      sort(buf_x, buf_x + k);
      for (int i = 0; i < k; i++) {
        sorted_x[i][j] = buf_x[i];
      }
      for (int i = 0; i < k; i++) {
        for (int ii = 0; ii < k; ii++) {
          if (x[ii][j] >= sorted_x[i][j]) {
            big_bitset[ii][len] = 1;
          } else {
            big_bitset[ii][len] = 0;
          }
        }
        len++;
      }
    }
  }
  fill_small();
  int len = k;
  for (int i = 0; i < q; i++) {
    int t, x, y;
    cin >> t >> x >> y;
    x--, y--;
    if (t == 1) {
      small_bitset[len++] = small_bitset[x] | small_bitset[y];
    }
    if (t == 2) {
      small_bitset[len++] = small_bitset[x] & small_bitset[y];
    }
    if (t == 3) {
      int ans = -1;
      for (int j = 0; j < k; j++) {
        int real_y = match[y * k + j];
        if (small_bitset[x][real_y]) {
          ans = sorted_x[j][y];
        }
      }
      cout << ans << "\n";
    }
  }
  return 0;
}
