#include <bits/stdc++.h>
const int SIZE_N = 100000 + 10;
const int SIZE_M = 100000 + 10;
int n, m;
int ary[SIZE_N * 2];
struct node {
  int le, ri, lc, rc;
  int ful, val;
  void show(void) { printf("%d %d %d %d %d %d\n", le, ri, lc, rc, ful, val); }
};
node tree[SIZE_N * 4];
int nno;
int init(int le, int ri) {
  int now = nno + 1;
  ++nno;
  tree[now].le = le, tree[now].ri = ri;
  tree[now].lc = tree[now].rc = 0;
  tree[now].ful = tree[now].val = 0;
  if (le == ri) return now;
  int mi = (le + ri >> 1);
  tree[now].lc = init(le, mi);
  tree[now].rc = init(mi + 1, ri);
  return now;
}
void update(int now, int ql, int qr, int val) {
  if (qr < ql) return;
  int le = tree[now].le, ri = tree[now].ri, lc = tree[now].lc,
      rc = tree[now].rc;
  int mi = (le + ri >> 1);
  if (ql == le && qr == ri) {
    tree[now].ful = 1, tree[now].val = val;
  } else {
    tree[now].ful = 0;
    if (lc != 0) update(lc, ql, std::min(qr, mi), val);
    if (rc != 0) update(rc, std::max(ql, mi + 1), qr, val);
  }
}
int query(int now, int qx) {
  int le = tree[now].le, ri = tree[now].ri, lc = tree[now].lc,
      rc = tree[now].rc;
  int mi = (le + ri >> 1);
  if (qx <= mi && lc != 0) return std::max(tree[now].val, query(lc, qx));
  if (mi + 1 <= qx && rc != 0) return std::max(tree[now].val, query(rc, qx));
  return tree[now].val;
}
int que[SIZE_M];
int main(void) {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; ++i) scanf("%d", ary + i);
  for (int i = 1; i <= n; ++i) scanf("%d", ary + n + i);
  nno = 0;
  init(1, n);
  update(1, 1, n, 0);
  que[0] = n;
  for (int count = 0, t, x, y, k; count < m; ++count) {
    scanf("%d", &t);
    if (t == 2) {
      scanf("%d", &x);
      int tem = query(1, x);
      tem = que[tem];
      printf("%d\n", ary[tem + x]);
    } else {
      scanf("%d%d%d", &x, &y, &k);
      update(1, y, y + k - 1, count + 1);
      que[count + 1] = x - y;
    }
  }
  return 0;
}
