#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int a[maxn], b[maxn], flat[maxn], par[maxn], bit[maxn], ans[maxn];
int up[maxn][16], tin[maxn], out[maxn], timedfs;
vector<int> adj[maxn];
set<int> pos[maxn];
int find(int u){
return par[u] == u ? u : par[u] = find(par[u]);
}
void dfs(int u){
tin[u] = ++timedfs;
flat[tin[u]] = b[u];
for(int v: adj[u]){
up[v][0] = u;
for(int j = 1; j <= 15; j++) up[v][j] = up[up[v][j - 1]][j - 1];
dfs(v);
}
out[u] = timedfs;
}
void update(int p, int v){
for (; p < maxn; p += p &- p) bit[p] += v;
}
int get(int p){
int res = 0;
for(; p; p -= p & -p) res += bit[p];
return res;
}
struct node{
int x, y, val, type, id;
};
vector<node> qry, mergesort;
void addpoint(int x, int y, int val){
qry.push_back({x, y + 1, val, 1, 0});
}
void addquery(int x, int y, int sign, int id){
qry.push_back({x, y + 1, sign, 2, id});
}
void cdq(int l, int r){
if(l >= r) return;
int mid = (l + r) / 2;
cdq(l, mid);
cdq(mid + 1, r);
int i = l, j = mid + 1, k = l;
while(i <= mid && j <= r){
if(qry[i].x <= qry[j].x){
if(qry[i].type == 1) update(qry[i].y, qry[i].val);
mergesort[k++] = qry[i++];
}else{
if(qry[j].type == 2) ans[qry[j].id] += qry[j].val * get(qry[j].y);
mergesort[k++] = qry[j++];
}
}
while(j <= r){
if(qry[j].type == 2) ans[qry[j].id] += qry[j].val * get(qry[j].y);
mergesort[k++] = qry[j++];
}
for(int p = l; p < i; p++){
if(qry[p].type == 1) update(qry[p].y, -qry[p].val);
}
while(i <= mid) mergesort[k++] = qry[i++];
for(int p = l; p <= r; p++) qry[p] = mergesort[p];
}
signed main(){
ios_base::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int r, c, q; cin >> r >> c >> q;
vector<array<int, 3>> val;
for(int i = 1; i <= r; i++){
for(int j = 1; j <= c; j++){
cin >> a[(i - 1) * c + j];
val.push_back({a[(i - 1) * c + j], i, j});
}
}
for(int i = 1; i <= r; i++){
for(int j = 1; j <= c; j++) cin >> b[(i - 1) * c + j];
}
sort(val.begin(), val.end());
for(int i = 1; i <= r * c; i++) par[i] = i;
array<pair<int, int>, 4> d = array<pair<int, int>, 4>{pair<int, int>{-1, 0}, pair<int, int>{1, 0}, pair<int, int>{0, 1}, pair<int, int>{0, -1}};
for(auto [_, x, y]: val){
int u = (x - 1) * c + y;
for(auto [dx, dy]: d){
int nx = x + dx, ny = y + dy;
if(nx < 1 || ny < 1 || nx > r || ny > c) continue;
int v = (nx - 1) * c + ny;
if(a[v] > a[u]) continue;
v = find(v);
par[v] = u;
if(v != u) adj[u].push_back(v);
}
}
int root = (val.back()[1] - 1) * c + val.back()[2];
for(int j = 0; j <= 15; j++) up[root][j] = root;
dfs(root);
for(int i = 1; i <= r * c; i++) pos[flat[i]].insert(i);
for(int i = 1; i <= 50000; i++){
int last = 0;
for(auto p: pos[i]){
addpoint(p, last, 1); //last = pre[i];
last = p;
}
}
int cnt = 0;
for(int i = 1; i <= q; i++){
int type, x, y, k; cin >> type >> y >> x >> k;
if(type == 1){
int u = (x - 1) * c + y, old = flat[tin[u]];
auto it = pos[old].find(tin[u]);
int pre = 0, nxt = 0;
if(it != pos[old].begin()) pre = *prev(it);
if(next(it) != pos[old].end()) nxt = *next(it);
pos[old].erase(it);
addpoint(tin[u], pre, -1); //xóa điểm (tin[u], pre)
if(nxt){
addpoint(nxt, tin[u], -1); //nếu có nxt xóa (nxt, tin[u]);
addpoint(nxt, pre, 1); //thêm điểm (nxt, pre)
}
pos[k].insert(tin[u]);
it = pos[k].find(tin[u]);
pre = 0; nxt = 0;
if(it != pos[k].begin()) pre = *prev(it);
if(next(it) != pos[k].end()) nxt = *next(it);
addpoint(tin[u], pre, 1);
if(nxt){
addpoint(nxt, tin[u], 1);
addpoint(nxt, pre, -1);
}
flat[tin[u]] = k;
}else{
int u = (x - 1) * c + y;
cnt++;
if(a[u] > k) continue;
for(int j = 15; j >= 0; j--){
if(a[up[u][j]] <= k) u = up[u][j];
}
int l = tin[u], r = out[u];
addquery(r, l - 1, 1, cnt);
addquery(l - 1, l - 1, -1, cnt);
}
}
mergesort.resize(qry.size());
cdq(0, qry.size() - 1);
for (int i = 1; i <= cnt; i++) cout << ans[i] << "\n";
}