#include <bits/stdc++.h>
#pragma GCC optimize("O2")
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
using namespace std;
const int N = 222222;
int n, m, a[N], b[N];
template <class T>
void cmax(T &x, T y) {
  x = x > y ? x : y;
}
template <class T>
void cmin(T &x, T y) {
  x = x < y ? x : y;
}
template <class T>
void rd(T &x) {
  char c = getchar();
  int f = 1;
  x = 0;
  for (; !isdigit(c); c = getchar())
    if (c == '-') f = -1;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  x *= f;
}
template <int S>
struct bs {
  bitset<N> tmp, b[N / S];
  int per[N];
  void ins(int pos, int v) {
    int i;
    per[pos] = v;
    for (i = pos; i <= n; i += S) b[i / S].set(v);
  }
  void del(int pos, int v) {
    int i;
    for (i = pos; i <= n; i += S) b[i / S].reset(v);
  }
  const bitset<N> qry(int x) {
    int i;
    tmp = x / S ? b[x / S - 1] : 0;
    for (i = max(x / S * S, 1); i <= x; ++i) tmp.set(per[i]);
    return tmp;
  }
  const bitset<N> query(int l, int r) { return qry(r) ^ qry(l - 1); }
};
bs<512> A;
bs<256> B;
int main() {
  int i;
  rd(n);
  rd(m);
  for (i = 1; i <= n; ++i) rd(a[i]), A.ins(i, a[i]);
  for (i = 1; i <= n; ++i) rd(b[i]), B.ins(i, b[i]);
  for (i = 1; i <= m; ++i) {
    int opt;
    rd(opt);
    if (opt == 1) {
      int l1, r1, l2, r2;
      rd(l1);
      rd(r1);
      rd(l2);
      rd(r2);
      printf("%d\n", (A.query(l1, r1) & B.query(l2, r2)).count());
    } else {
      int x, y;
      rd(x);
      rd(y);
      B.del(x, b[x]), B.del(y, b[y]), swap(b[x], b[y]);
      B.ins(x, b[x]), B.ins(y, b[y]);
    }
  }
  return 0;
}
