#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const long long LINF = 0x3f3f3f3f3f3f3f3fll;
const long double pi = acos(-1);
const int MOD = 1e9 + 7;
const int N = 2e5 + 100;
int tr_min[4 * N][1 << 5];
int tr_max[4 * N][1 << 5];
vector<int> cara[N];
int n, k;
void build(int node, int b, int e) {
  if (b == e) {
    for (int cord = 0; cord < (1 << k); cord++) {
      long long x = 0;
      for (int i = 0; i < k; i++) {
        if (cord & (1 << i))
          x += cara[b][i];
        else
          x -= cara[b][i];
      }
      tr_max[node][cord] = tr_min[node][cord] = x;
    }
  } else {
    int mid = (b + e) / 2;
    build(2 * node, b, mid);
    build(2 * node + 1, mid + 1, e);
    for (int i = 0; i < (1 << k); i++) {
      tr_max[node][i] = max(tr_max[2 * node][i], tr_max[2 * node + 1][i]);
      tr_min[node][i] = min(tr_min[2 * node][i], tr_min[2 * node + 1][i]);
    }
  }
}
void update(int node, int b, int e, int i, vector<int> &cara) {
  if (e < i or b > i) return;
  if (b == e and b == i) {
    for (int cord = 0; cord < (1 << k); cord++) {
      long long x = 0;
      for (int i = 0; i < k; i++) {
        if (cord & (1 << i))
          x += cara[i];
        else
          x -= cara[i];
      }
      tr_max[node][cord] = tr_min[node][cord] = x;
    }
    return;
  }
  int mid = (b + e) / 2;
  update(2 * node, b, mid, i, cara);
  update(2 * node + 1, mid + 1, e, i, cara);
  for (int i = 0; i < (1 << k); i++) {
    tr_max[node][i] = max(tr_max[2 * node][i], tr_max[2 * node + 1][i]);
    tr_min[node][i] = min(tr_min[2 * node][i], tr_min[2 * node + 1][i]);
  }
}
int query(int node, int b, int e, int i, int j, int cord) {
  if (e < i or b > j) return -INF;
  if (i <= b and j >= e) {
    return tr_max[node][cord];
  }
  int mid = (b + e) / 2;
  return max(query(2 * node, b, mid, i, j, cord),
             query(2 * node + 1, mid + 1, e, i, j, cord));
}
int query2(int node, int b, int e, int i, int j, int cord) {
  if (e < i or b > j) return INF;
  if (i <= b and j >= e) {
    return tr_min[node][cord];
  }
  int mid = (b + e) / 2;
  return min(query2(2 * node, b, mid, i, j, cord),
             query2(2 * node + 1, mid + 1, e, i, j, cord));
}
int proc(int cord, int l, int r) {
  int maxi = query(1, 1, n, l, r, cord);
  int mini = query2(1, 1, n, l, r, cord);
  return abs(mini - maxi);
}
int main() {
  scanf("%d %d", &n, &k);
  for (int i = 1; i <= n; i++) {
    for (int j = 0; j < k; j++) {
      int x;
      scanf("%d", &x);
      cara[i].push_back(x);
    }
  }
  int q;
  build(1, 1, n);
  scanf("%d", &q);
  while (q--) {
    int op;
    scanf("%d", &op);
    if (op == 1) {
      int idx;
      scanf("%d", &idx);
      vector<int> val;
      for (int j = 0; j < k; j++) {
        int x;
        scanf("%d", &x);
        val.push_back(x);
      }
      update(1, 1, n, idx, val);
    } else {
      int l, r;
      scanf("%d %d", &l, &r);
      int resp = 0;
      for (int i = 0; i < (1 << k); i++) resp = max(proc(i, l, r), resp);
      printf("%d\n", resp);
    }
  }
}
