#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
char _buf[100000], *_p1 = _buf, *_p2 = _buf;
inline int gi() {
  int x = 0, f = 1;
  char ch = (_p1 == _p2 && (_p2 = (_p1 = _buf) + fread(_buf, 1, 100000, stdin),
                            _p1 == _p2)
                 ? EOF
                 : *_p1++);
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = (_p1 == _p2 && (_p2 = (_p1 = _buf) + fread(_buf, 1, 100000, stdin),
                         _p1 == _p2)
              ? EOF
              : *_p1++);
  }
  while (ch >= '0' && ch <= '9') {
    x = (x << 3) + (x << 1) + (ch ^ 48);
    ch = (_p1 == _p2 && (_p2 = (_p1 = _buf) + fread(_buf, 1, 100000, stdin),
                         _p1 == _p2)
              ? EOF
              : *_p1++);
  }
  return (f == 1) ? x : -x;
}
inline int max(int a, int b) { return a > b ? a : b; }
inline int min(int a, int b) { return a < b ? a : b; }
const int maxn = 1e5 + 5;
bitset<4096> f[maxn];
int a[13][maxn];
int tot, n, k, q;
inline void init() {}
inline void input() {
  n = gi(), k = gi(), q = gi();
  for (int i = 1; i <= k; ++i)
    for (int j = 1; j <= n; ++j) a[i][j] = gi();
  tot = k;
}
inline void solve() {
  for (int i = 1; i <= k; ++i)
    for (int j = 0; j <= (1 << k) - 1; ++j)
      if (j >> (i - 1) & 1) f[i][j] = 1;
  for (int i = 1; i <= q; ++i) {
    int t = gi(), x = gi(), y = gi();
    if (t == 1)
      f[++tot] = f[x] | f[y];
    else if (t == 2)
      f[++tot] = f[x] & f[y];
    else {
      vector<pair<int, int> > vec;
      for (int j = 1; j <= k; ++j)
        vec.push_back(pair<int, int>(a[j][y], j - 1));
      sort(vec.begin(), vec.end(), greater<pair<int, int> >());
      int S = 0;
      for (int i = 0; i <= k - 1; ++i) {
        S |= (1 << vec[i].second);
        if (f[x][S]) {
          printf("%d\n", vec[i].first);
          break;
        }
      }
    }
  }
}
int main() {
  int T = 1;
  while (T--) {
    init();
    input();
    solve();
  }
  return 0;
}
