#include <bits/stdc++.h>
#pragma GGC optimize("Ofast")
using namespace std;
template <typename T>
void dprintln(const T &t) {
  cout << t << endl;
}
template <typename T, typename... Args>
void dprintln(const T &t, const Args &...rest) {
  cout << t << ' ';
  dprintln(rest...);
}
template <typename T>
void println(const T &t) {
  cout << t << '\n';
}
template <typename T, typename... Args>
void println(const T &t, const Args &...rest) {
  cout << t << ' ';
  println(rest...);
}
template <typename T>
void print(const T &t) {
  cout << t << ' ';
}
template <typename T, typename... Args>
void print(const T &t, const Args &...rest) {
  cout << t << ' ';
  print(rest...);
}
template <class T>
void scan(T &t) {
  cin >> t;
}
template <class T, class... Args>
void scan(T &a, Args &...rest) {
  cin >> a;
  scan(rest...);
}
using ll = long long;
using vl = vector<ll>;
using vi = vector<int>;
using pii = pair<int, int>;
using vb = vector<bool>;
using vpii = vector<pii>;
template <typename T>
struct bit {
  vector<T> a;
  explicit bit(int n, int v = 0) {
    a.resize(n + 1);
    if (v != 0) {
      for (int i = 1; i <= n; ++i) a[i] = v;
    }
  }
  T sum(T x) {
    T res = 0;
    while (x) {
      res += a[x];
      x -= x & -x;
    }
    return res;
  }
  T sum(int l, int r) {
    if (l > r) return 0;
    return sum(r) - sum(l - 1);
  }
  void add(int x, T v) {
    while (x < a.size()) {
      a[x] += v;
      x += x & -x;
    }
  }
  void clear() { fill(a.begin(), a.end(), 0); }
};
vi get_prime(int n) {
  vi minp(n + 1), p;
  for (int i = 2; i <= n; i++) {
    if (!minp[i]) {
      minp[i] = i;
      p.push_back(i);
    }
    for (auto &x : p) {
      if (x <= minp[i] && x * i <= n)
        minp[x * i] = x;
      else
        break;
    }
  }
  return p;
}
const int mod = 998244353;
inline void add_mod(ll &x, const ll &y) {
  x += y;
  if (x >= mod) x -= mod;
}
void sub_mod(ll &x, const ll &y) {
  x -= y;
  if (x < 0) x += mod;
}
template <typename T>
using vv = vector<vector<T>>;
template <typename T1, typename T2 = T1>
using vp = vector<pair<T1, T2>>;
template <typename T, int n>
using va = vector<array<T, n>>;
using vec = vector<ll>;
using mat = vector<vec>;
mat get_I(int n) {
  mat res(n, vec(n));
  for (int i = 0; i < n; i++) res[i][i] = 1;
  return res;
}
mat operator*(const mat &a, const mat &b) {
  mat c(a.size(), vec(b[0].size()));
  for (size_t i = 0; i < a.size(); i++) {
    for (size_t j = 0; j < a[0].size(); j++) {
      if (a[i][j]) {
        for (size_t k = 0; k < b[0].size(); k++) {
          add_mod(c[i][k], a[i][j] * b[j][k] % mod);
        }
      }
    }
  }
  return c;
}
vec operator*(const mat &a, const vec &b) {
  vec c(a.size());
  for (size_t i = 0; i < a.size(); i++) {
    for (size_t j = 0; j < a[0].size(); j++) {
      add_mod(c[i], a[i][j] * b[j] % mod);
    }
  }
  return c;
}
mat pow(mat a, ll n) {
  mat res(a.size(), vec(a[0].size()));
  for (size_t i = 0; i < a.size(); i++) {
    res[i][i] = 1;
  }
  while (n) {
    if (n & 1) {
      res = res * a;
    }
    a = a * a;
    n >>= 1;
  }
  return res;
}
struct UF {
  vi par;
  explicit UF(int n) {
    par.assign(n + 1, 0);
    for (int i = (1); i < (n + 1); ++i) par[i] = i;
  }
  int find(int x) { return x == par[x] ? x : par[x] = find(par[x]); }
  void unite(int x, int y) { par[find(x)] = find(y); }
};
vi get_popcnt(int n) {
  vi res(n + 1);
  for (int i = (0); i < (n); ++i) {
    if (i * 2 <= n) res[i * 2] = res[i];
    if ((i & 1) == 0) res[i + 1] = res[i] + 1;
  }
  return res;
}
const int N = 2e3 + 5;
struct edge {
  int u, v, w;
  void read() { scan(u, v, w); }
  bool operator<(const edge &b) const { return w < b.w; };
};
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n, m;
  scan(n, m);
  vi a(n + 1), b(n + 1);
  vi posa(n + 1), posb(n + 1);
  for (int i = (1); i < (n + 1); ++i) cin >> a[i], posa[a[i]] = i;
  for (int i = (1); i < (n + 1); ++i) cin >> b[i], posb[b[i]] = i;
  int k = 3358;
  vi bucket(n + 1);
  for (int i = (1); i < (n + 1); ++i) bucket[i] = i / k;
  vector<bit<int>> c(n / k + 1, bit<int>(n));
  auto query = [&](int la, int ra, int lb, int rb) {
    int t = (bucket[la] + 1) * k;
    int ans = 0;
    for (int i = (la); i < (min(t, ra + 1)); ++i) {
      ans += lb <= posb[a[i]] && posb[a[i]] <= rb;
    }
    for (int i = (bucket[la] + 1); i < (bucket[ra]); ++i) {
      ans += c[i].sum(lb, rb);
    }
    t = max(bucket[la] + 1, bucket[ra]) * k;
    for (int i = (t); i < (ra + 1); ++i) {
      ans += lb <= posb[a[i]] && posb[a[i]] <= rb;
    }
    return ans;
  };
  auto upd_bit = [&](int i, int j) { c[bucket[posa[b[i]]]].add(i, j); };
  auto upd = [&](int i, int j) {
    upd_bit(i, -1);
    upd_bit(j, -1);
    swap(b[i], b[j]);
    swap(posb[b[i]], posb[b[j]]);
    upd_bit(i, 1);
    upd_bit(j, 1);
  };
  for (int i = (1); i < (n + 1); ++i) {
    upd_bit(i, 1);
  }
  for (int _ = 0, __ = (int)m; _ < __; _++) {
    int t;
    scan(t);
    if (t == 1) {
      int la, ra, lb, rb;
      scan(la, ra, lb, rb);
      println(query(la, ra, lb, rb));
    } else {
      int x, y;
      scan(x, y);
      upd(x, y);
    }
  }
  return 0;
}
