#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
const int inf = 1e9;
const long long Inf = 1e15;
inline int IN() {
  char ch = getchar();
  int x = 0, f = 0;
  while (ch < '0' || ch > '9') ch = getchar(), f = (ch == '-');
  while (ch >= '0' && ch <= '9') {
    x = (x << 1) + (x << 3) + ch - 48;
    ch = getchar();
  }
  return f ? (-x) : x;
}
inline int Pow(int x, int y, int p) {
  int an = 1;
  for (; y; y >>= 1, x = (long long)x * x % p)
    if (y & 1) an = (long long)an * x % p;
  return an;
}
void setIO(string a) {
  freopen((a + ".in").c_str(), "r", stdin);
  freopen((a + ".out").c_str(), "w", stdout);
}
template <typename T>
inline void chkmin(T &a, const T &b) {
  if (a > b) a = b;
}
template <typename T>
inline void chkmax(T &a, const T &b) {
  if (a < b) a = b;
}
int v[100005][15], cnt, n, k, q;
bitset<4100> A[100050];
int id[100005][15], cmpd;
int cmp(const int &a, const int &b) { return v[cmpd][a] <= v[cmpd][b]; }
int main() {
  scanf("%d%d%d", &n, &k, &q);
  for (int i = (int)1; i <= (int)k; i++)
    for (int j = (int)1; j <= (int)n; j++) scanf("%d", &v[j][i]);
  for (int i = (int)1; i <= (int)k; i++) {
    for (int j = (int)0; j < (int)1 << k; j++)
      if ((j >> (i - 1)) & 1) A[i].set(j);
  }
  for (int i = (int)1; i <= (int)n; i++) {
    for (int j = (int)1; j <= (int)k; j++) id[i][j] = j;
    cmpd = i;
    sort(id[i] + 1, id[i] + k + 1, cmp);
  }
  int xk = k;
  for (int i = (int)1; i <= (int)q; i++) {
    int t, x, y;
    scanf("%d%d%d", &t, &x, &y);
    if (t == 1) {
      ++k;
      A[k] = A[x] & A[y];
    } else if (t == 2) {
      ++k;
      A[k] = A[x] | A[y];
    } else {
      int S = 0, ans;
      for (int j = (int)1; j <= (int)xk; j++) {
        int u = id[y][j];
        S |= 1 << (u - 1);
        if (A[x][S]) {
          ans = v[y][u];
          break;
        }
      }
      printf("%d\n", ans);
    }
  }
  return 0;
}
