#include <bits/stdc++.h>
const int N = 1e5 + 5;
std::bitset<1 << 12> f[N + 20];
int cnt;
struct node {
  int val, id;
  bool operator<(const node& A) const { return val > A.val; }
};
std::vector<node> v[N];
int all;
void print(int k) {
  for (int i = 0; i <= all; i++) {
    printf("%d:", i);
    if (f[k][i])
      printf("1 ");
    else
      printf("0 ");
  }
  puts("");
  return;
}
int main() {
  int n, m, q;
  scanf("%d %d %d", &n, &m, &q);
  all = (1 << m) - 1;
  cnt = m - 1;
  for (int k = 0; k < m; k++)
    for (int j = 1; j <= n; j++) {
      int a;
      scanf("%d", &a);
      v[j].push_back((node){a, k});
    }
  for (int j = 1; j <= n; j++) std::sort(v[j].begin(), v[j].end());
  for (int k = 0; k < m; k++)
    for (int s = 0; s <= all; s++)
      if (s & 1 << k) f[k][s] = 1;
  int op, x, y;
  while (q--) {
    scanf("%d %d %d", &op, &x, &y);
    x--, y--;
    if (op == 1)
      f[++cnt] = f[x] | f[y];
    else if (op == 2)
      f[++cnt] = f[x] & f[y];
    else {
      int s = 0;
      y++;
      for (int i = 0; i < v[y].size(); i++) {
        s |= 1 << v[y][i].id;
        if (f[x][s]) {
          printf("%d\n", v[y][i].val);
          break;
        }
      }
    }
  }
  return 0;
}
