Problem: The maps in the game are divided into square cells called Geo Panels. Some of these panels are painted. We shall assume that the Geo Panels without color are painted the transparent color. 

Besides, the map has so-called Geo Symbols. They look like pyramids of different colors (including Geo Symbols of the transparent color). Each Geo Symbol is located on one Geo Panel, and each Geo Panel may contain no more than one Geo Symbol. 

Geo Symbols can be eliminated. To understand better what happens when a Geo Symbol is eliminated, let us introduce some queue to which we will put the recently eliminated Geo Symbols. 

Let's put at the head of the queue a Geo Symbol that was eliminated just now. Next, we will repeat the following operation: 

Extract the Geo Symbol from the queue. Look at the color of the panel containing the given Geo Symbol. If it differs from transparent and differs from the color of the Geo Symbol, then all Geo Panels of this color are repainted in the color of the given Geo Symbol (transparent Geo Symbols repaint the Geo Panels transparent). Repainting is executed in an infinite spiral strictly in the following order starting from the panel, which contained the Geo Symbol: 

<image>

In other words, we select all the panels that need to be repainted and find their numbers in the infinite spiral whose center is placed in the position of the given Geo Symbol. After that, we repaint them in the order of the number's increasing. 

If a panel contains another Geo Symbol and this panel is being repainted, then the Geo Symbol is removed from the field and placed at the tail of the queue. 

After repainting the Geo Symbol is completely eliminated and the next Geo Symbol is taken from the head of the queue (if there is any) and the process repeats. The process ends if the queue is empty. 

See the sample analysis for better understanding. 

You know the colors of all the Geo Panels and the location of all the Geo Symbols. Determine the number of repaintings, which will occur if you destroy one of the Geo Symbols.

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 300) — the height and the width of the map (in cells).

Then follow n line; each of them contains m numbers — the Geo Panels' colors.

Then follow n more lines; each of them contains m numbers — the Geo Symbols' description. -1 means that the given position contains no Geo Symbol. Otherwise, the number represents the color of the Geo Symbol in the given position.

All colors are integers from 0 to 109. 0 represents the transparent color.

The last line contains two integers x and y (1 ≤ x ≤ n, 1 ≤ y ≤ m) — the row and the column where the Geo Symbol is placed that needs to be eliminated. The rows are numbered from top to bottom, the columns are numbered from left to right. Coordinates are 1-based. It is guaranteed that the position with coordinates (x, y) contains a Geo Symbol.

Output

Print the single number — the total number of repaintings after the Geo Symbol is eliminated. 

Please, do not use the %lld specificator to read or write 64-bit integers in C++. It is preferred to use the cout stream (you may also use the %I64d specificator).

Examples

Input

5 5
9 0 1 1 0
0 0 3 2 0
1 1 1 3 0
1 1 1 3 0
0 1 2 0 3
-1 1 -1 3 -1
-1 -1 -1 0 -1
-1 -1 -1 -1 -1
-1 2 3 -1 -1
-1 -1 -1 -1 2
4 2


Output

35

Note

All actions of the sample you can see on the following picture: 

<image> If your browser does not support APNG and you see just static image, you can see GIF version of this image by the following link:

http://assets.codeforces.com/images/geo_slow.gif

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
const int MAX = 900010, MAX2 = 305;
struct node {
  int parent;
  int ranks;
};
node trees[MAX];
int findSet(int x) {
  if (trees[x].parent != x)
    return trees[x].parent = findSet(trees[x].parent);
  else
    return x;
}
void unions(int x, int y) {
  int rootX = findSet(x), rootY = findSet(y);
  if (rootX == rootY) return;
  if (trees[rootX].ranks > trees[rootY].ranks) swap(rootX, rootY);
  trees[rootX].parent = rootY;
  if (trees[rootX].ranks == trees[rootY].ranks) trees[rootY].ranks++;
}
unordered_map<int, int> ls;
int ysc[MAX], rootC[MAX], root1[MAX], size[MAX];
vector<pair<int, int> > tt[MAX];
int mm[MAX2][MAX2], mm2[MAX2][MAX2];
int cnt, n, m, x, y;
struct ggt {
  int x, y, co;
  ggt(int a = 0, int b = 0, int c = 0) : x(a), y(b), co(c) {}
};
vector<ggt> jz[MAX];
inline int code(const pair<int, int> &a) { return a.first * m + a.second; }
inline pair<int, int> decode(int n) {
  int s = n / m, r = n % m;
  if (r == 0)
    return {s - 1, m - 1};
  else
    return {s, r - 1};
}
inline int getT(const ggt &a, int x, int y, int ma) {
  int l = y - ma, r = y + ma, u = x - ma, b = x + ma;
  if (a.x == u && a.y >= l + 1 && a.y <= r - 1)
    return 0;
  else if (a.y == r && a.x >= u && a.x <= b - 1)
    return 1;
  else if (a.x == b && a.y >= l + 1 && a.y <= r)
    return 2;
  else
    return 3;
}
struct cmp {
  int x, y;
  cmp(int a = 0, int b = 0) : x(a), y(b) {}
  bool operator()(const ggt &a, const ggt &b) {
    int ma = max(abs(a.x - x), abs(a.y - y));
    int mb = max(abs(b.x - x), abs(b.y - y));
    if (ma != mb)
      return ma < mb;
    else {
      int ta = getT(a, x, y, ma), tb = getT(b, x, y, ma);
      if (ta != tb)
        return ta < tb;
      else {
        if (ta == 0)
          return a.y < b.y;
        else if (ta == 1)
          return a.x < b.x;
        else if (ta == 2)
          return a.y > b.y;
        else
          return a.x > b.x;
      }
    }
  }
};
int main() {
  scanf("%d%d\n", &n, &m);
  cnt = 0;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      scanf("%d", &mm[i][j]);
      if (ls.find(mm[i][j]) == ls.end()) ls[mm[i][j]] = cnt++;
    }
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      scanf("%d", &mm2[i][j]);
      if (mm2[i][j] != -1) {
        if (ls.find(mm2[i][j]) == ls.end()) ls[mm2[i][j]] = cnt++;
      }
    }
  }
  scanf("%d%d", &x, &y);
  x--, y--;
  for (auto &ele : ls) {
    ysc[ele.second] = ele.first;
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      int cc = ls[mm[i][j]];
      tt[cc].push_back({i, j});
    }
  }
  for (int i = 0; i < n * m; i++) trees[i].parent = i, trees[i].ranks = 0;
  memset(root1, -1, sizeof(root1));
  for (int i = 0; i < cnt; i++) {
    if (tt[i].size()) {
      for (int j = 1; j < tt[i].size(); j++) {
        int pos = code({tt[i][j].first, tt[i][j].second});
        int prev = code({tt[i][j - 1].first, tt[i][j - 1].second});
        unions(pos, prev);
      }
      int pos = code({tt[i][0].first, tt[i][0].second});
      int r = findSet(pos);
      rootC[r] = i;
      root1[i] = r;
      size[i] = tt[i].size();
    }
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (!(i == x && j == y)) {
        if (mm2[i][j] != -1) {
          int c = ls[mm2[i][j]];
          int color = ls[mm[i][j]];
          jz[color].push_back({i, j, c});
        }
      }
    }
  }
  int sy = ls[mm2[x][y]];
  queue<ggt> Q;
  Q.push({x, y, sy});
  long long ans = 0;
  while (!Q.empty()) {
    ggt cur = Q.front();
    Q.pop();
    int x = cur.x, y = cur.y, c2 = cur.co;
    int bh = code({x, y});
    int bhr = findSet(bh);
    int color = rootC[bhr], color2 = ysc[color];
    if (color2 != 0 && c2 != color) {
      ans += size[color];
      if (root1[c2] == -1) {
        root1[c2] = bhr;
        rootC[bhr] = c2;
        root1[color] = -1;
        size[c2] = size[color];
        size[color] = 0;
      } else {
        int nr = root1[c2];
        unions(nr, bhr);
        int newr = findSet(nr);
        rootC[newr] = c2;
        root1[c2] = newr;
        root1[color] = -1;
        size[c2] += size[color];
        size[color] = 0;
      }
      sort(jz[color].begin(), jz[color].end(), cmp(x, y));
      for (int i = 0; i < jz[color].size(); i++) {
        Q.push(jz[color][i]);
      }
      jz[color].resize(0);
    }
  }
  printf("%lld\n", ans);
  return 0;
}