//I_l_M_P
#include <bits/stdc++.h>

#ifdef FAST_ALLOCATOR_MEMORY
int allocator_pos = 0;
char allocator_memory[(int)FAST_ALLOCATOR_MEMORY];
inline void * operator new ( size_t n ) {
  char *res = allocator_memory + allocator_pos;
  allocator_pos += n;
  assert(allocator_pos <= (int)FAST_ALLOCATOR_MEMORY);
  return (void *)res;
}
inline void operator delete ( void * ) noexcept { }
//inline void * operator new [] ( size_t ) { assert(0); }
//inline void operator delete [] ( void * ) { assert(0); }
#endif

template <class T = int> inline T readInt();
inline double readDouble();
inline int readUInt();
inline int readChar();
inline void readWord(char *s);
inline bool readLine(char *s);
inline bool isEof();
inline int getChar();
inline int peekChar();
inline bool seekEof();
inline void skipBlanks();

template <class T> inline void writeInt(T x, char end = 0, int len = -1);
inline void writeChar(int x);
inline void writeWord(const char *s);
inline void writeDouble(double x, int len = 0);
inline void flush();

static struct buffer_flusher_t {
  ~buffer_flusher_t() {
    flush();
  }
} buffer_flusher;

static const int buf_size = 4096;

static unsigned char buf[buf_size];
static int buf_len = 0, buf_pos = 0;

inline bool isEof() {
  if (buf_pos == buf_len) {
    buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
    if (buf_pos == buf_len)
      return 1;
  }
  return 0;
}

inline int getChar() {
  return isEof() ? -1 : buf[buf_pos++];
}

inline int peekChar() {
  return isEof() ? -1 : buf[buf_pos];
}

inline bool seekEof() {
  int c;
  while ((c = peekChar()) != -1 && c <= 32)
    buf_pos++;
  return c == -1;
}

inline void skipBlanks() {
  while (!isEof() && buf[buf_pos] <= 32U)
    buf_pos++;
}

inline int readChar() {
  int c = getChar();
  while (c != -1 && c <= 32)
    c = getChar();
  return c;
}

inline int readUInt() {
  int c = readChar(), x = 0;
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return x;
}

template <class T>
inline T readInt() {
  int s = 1, c = readChar();
  T x = 0;
  if (c == '-')
    s = -1, c = getChar();
  else if (c == '+')
    c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return s == 1 ? x : -x;
}

inline double readDouble() {
  int s = 1, c = readChar();
  double x = 0;
  if (c == '-')
    s = -1, c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  if (c == '.') {
    c = getChar();
    double coef = 1;
    while ('0' <= c && c <= '9')
      x += (c - '0') * (coef *= 1e-1), c = getChar();
  }
  return s == 1 ? x : -x;
}

inline void readWord(char *s) {
  int c = readChar();
  while (c > 32)
    *s++ = c, c = getChar();
  *s = 0;
}

inline bool readLine(char *s) {
  int c = getChar();
  while (c != '\n' && c != -1)
    *s++ = c, c = getChar();
  *s = 0;
  return c != -1;
}

static int write_buf_pos = 0;
static char write_buf[buf_size];

inline void writeChar( int x ) {
  if (write_buf_pos == buf_size)
    fwrite(write_buf, 1, buf_size, stdout), write_buf_pos = 0;
  write_buf[write_buf_pos++] = x;
}

inline void flush() {
  if (write_buf_pos) {
    fwrite(write_buf, 1, write_buf_pos, stdout), write_buf_pos = 0;
    fflush(stdout);
  }
}

template <class T>
inline void writeInt(T x, char end, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  char s[24];
  int n = 0;
  while (x || !n)
    s[n++] = '0' + x % 10, x /= 10;
  while (n < output_len)
    s[n++] = '0';
  while (n--)
    writeChar(s[n]);
  if (end)
    writeChar(end);
}

inline void writeWord(const char *s) {
  while (*s)
    writeChar(*s++);
}

inline void writeDouble(double x, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  int t = (int)x;
  writeInt(t), x -= t;
  writeChar('.');
  for (int i = output_len - 1; i > 0; i--) {
    x *= 10;
    t = std::min(9, (int)x);
    writeChar('0' + t), x -= t;
  }
  x *= 10;
  t = std::min(9, (int)(x + 0.5));
  writeChar('0' + t);
}

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")

using namespace std;

typedef long double ld;
typedef long long ll;

#define _ inline
#define f first
#define sec second
#define pb push_back
#define ins insert
#define ers erase
#define mk make_pair
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
//#define int ll

#define right rightt
#define left leftt
#define prev prevv
#define next nextt

mt19937 Random(time(0));

const int INF = 1e9 + 10;
const int MOD = 1e9 + 7;
const int P = 239017;
const long long BINF = 1e18 + 10;

struct SQRT_Decomposition {
  vector<int> L, L2, R, R2, T, arr;
  vector<map<int, int> > cnt;
  int n, cnt_blocks, len;
  SQRT_Decomposition(vector<int> _arr, int _n) {
    arr = _arr;
    n = _n;
    build();
  }
  void out() {
    for (auto it : T) {
      for (int i = L[it]; i <= R[it]; i++) {
        writeInt(arr[i], ' ');
      }
    }
    writeChar('\n');
  }
  void build() {
    cnt_blocks = (int)sqrt(n);
    len = n / cnt_blocks;
    if (cnt_blocks * len < n) {
      len++;
    }
    L.rsz(cnt_blocks);
    R.rsz(cnt_blocks);
    L2.rsz(cnt_blocks);
    R2.rsz(cnt_blocks);
    T.rsz(cnt_blocks);
    cnt.rsz(cnt_blocks);
    for (int i = 0; i < cnt_blocks; i++) {
      L[i] = len * i;
      R[i] = min(len * (i + 1), n) - 1;
      L2[i] = L[i], R2[i] = R[i];
      T[i] = i;
      for (int j = L[i]; j <= R[i]; j++) {
        cnt[i][arr[j]]++;
      }
    }
  }
  void rebuild() {
    vector<int> arr2;
    for (auto it : T) {
      for (int i = L[it]; i <= R[it]; i++) {
        arr2.pb(arr[i]);
      }
    }
    arr = arr2;
    for (int i = 0; i < cnt_blocks; i++) {
      cnt[i].clear();
    }
    build();
  }
  void create_new_block(int l, int r, int l2, int r2) {
    L.pb(l);
    R.pb(r);
    L2.pb(l2);
    R2.pb(r2);
    cnt.pb({});
    for (int i = l; i <= r; i++) {
      cnt[cnt_blocks][arr[i]]++;
    }
    cnt_blocks++;
  }
  void split(int x) {
    int ind = -1, pos = 0;
    for (auto it : T) {
      if (L2[it] <= x && R2[it] >= x) {
        ind = it;
        break;
      }
      pos++;
    }
    if (ind == -1 || R2[ind] == x) {
      return;
    }
    int ln = x - L2[ind];
    create_new_block(L[ind], L[ind] + ln, L2[ind], x);
    create_new_block(L[ind] + ln + 1, R[ind], x + 1, R2[ind]);
    vector<int> T2;
    for (int i = 0; i < pos; i++) {
      T2.pb(T[i]);
    }
    T2.pb(cnt_blocks - 2);
    T2.pb(cnt_blocks - 1);
    for (int i = pos + 1; i < (int)T.size(); i++) {
      T2.pb(T[i]);
    }
    T = T2;
  }
  void cut(int l, int r) {
    split(l - 1);
    split(r - 1);
    split(r);
    int pos1, pos2;
    for (int i = 0; i < (int)T.size(); i++) {
      if (L2[T[i]] == l) {
        pos1 = i;
      }
      if (R2[T[i]] == r) {
        pos2 = i;
      }
    }
    vector<int> T2;
    for (int i = 0; i < pos1; i++) {
      T2.pb(T[i]);
    }
    T2.pb(T[pos2]);
    for (int i = pos1; i < pos2; i++) {
      T2.pb(T[i]);
    }
    for (int i = pos2 + 1; i < (int)T.size(); i++) {
      T2.pb(T[i]);
    }
    T = T2;
    int cur = 0;
    for (auto it : T) {
      L2[it] = cur;
      R2[it] = cur + R[it] - L[it];
      cur = R2[it] + 1;
    }
  }
  int get(int l, int r, int k) {
    split(l - 1);
    split(r);
    int res = 0;
    for (auto it : T) {
      if (L2[it] >= l && R2[it] <= r) {
        res += cnt[it][k];
      }
    }
    return res;
  }
};

void source() {
  int n = readInt();
  vector<int> arr(n);
  for (auto &it : arr) {
    it = readInt();
  }
  SQRT_Decomposition A(arr, n);
  int m = readInt(), sz = (int)sqrt(n);
  int ans = 0;
  for (int i = 1; i <= m; i++) {
    if (A.cnt_blocks >= 4 * sz) {
      A.rebuild();
    }
    int type = readInt();
    if (type == 1) {
      int cur_l = readInt(), cur_r = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n;
      if (l > r) {
        swap(l, r);
      }
      A.cut(l, r);
    }
    else {
      int cur_l = readInt(), cur_r = readInt(), cur_k = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n, k = (cur_k + ans - 1) % n + 1;
      if (l > r) {
        swap(l, r);
      }
      ans = A.get(l, r, k);
      writeInt(ans, '\n');
    }
    //A.out();
  }
}

signed main() {
#ifdef EXTRATERRESTRIAL_
  assert(freopen("input.txt", "r", stdin));
  //assert(freopen("output.txt", "w", stdout));
#else
  //freopen(TASK".in", "r", stdin);
  //freopen(TASK".out", "w", stdout);
#endif
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  source();
  return 0;
}


//I_l_M_P
#include <bits/stdc++.h>

#ifdef FAST_ALLOCATOR_MEMORY
int allocator_pos = 0;
char allocator_memory[(int)FAST_ALLOCATOR_MEMORY];
inline void * operator new ( size_t n ) {
  char *res = allocator_memory + allocator_pos;
  allocator_pos += n;
  assert(allocator_pos <= (int)FAST_ALLOCATOR_MEMORY);
  return (void *)res;
}
inline void operator delete ( void * ) noexcept { }
//inline void * operator new [] ( size_t ) { assert(0); }
//inline void operator delete [] ( void * ) { assert(0); }
#endif

template <class T = int> inline T readInt();
inline double readDouble();
inline int readUInt();
inline int readChar();
inline void readWord(char *s);
inline bool readLine(char *s);
inline bool isEof();
inline int getChar();
inline int peekChar();
inline bool seekEof();
inline void skipBlanks();

template <class T> inline void writeInt(T x, char end = 0, int len = -1);
inline void writeChar(int x);
inline void writeWord(const char *s);
inline void writeDouble(double x, int len = 0);
inline void flush();

static struct buffer_flusher_t {
  ~buffer_flusher_t() {
    flush();
  }
} buffer_flusher;

static const int buf_size = 4096;

static unsigned char buf[buf_size];
static int buf_len = 0, buf_pos = 0;

inline bool isEof() {
  if (buf_pos == buf_len) {
    buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
    if (buf_pos == buf_len)
      return 1;
  }
  return 0;
}

inline int getChar() {
  return isEof() ? -1 : buf[buf_pos++];
}

inline int peekChar() {
  return isEof() ? -1 : buf[buf_pos];
}

inline bool seekEof() {
  int c;
  while ((c = peekChar()) != -1 && c <= 32)
    buf_pos++;
  return c == -1;
}

inline void skipBlanks() {
  while (!isEof() && buf[buf_pos] <= 32U)
    buf_pos++;
}

inline int readChar() {
  int c = getChar();
  while (c != -1 && c <= 32)
    c = getChar();
  return c;
}

inline int readUInt() {
  int c = readChar(), x = 0;
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return x;
}

template <class T>
inline T readInt() {
  int s = 1, c = readChar();
  T x = 0;
  if (c == '-')
    s = -1, c = getChar();
  else if (c == '+')
    c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return s == 1 ? x : -x;
}

inline double readDouble() {
  int s = 1, c = readChar();
  double x = 0;
  if (c == '-')
    s = -1, c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  if (c == '.') {
    c = getChar();
    double coef = 1;
    while ('0' <= c && c <= '9')
      x += (c - '0') * (coef *= 1e-1), c = getChar();
  }
  return s == 1 ? x : -x;
}

inline void readWord(char *s) {
  int c = readChar();
  while (c > 32)
    *s++ = c, c = getChar();
  *s = 0;
}

inline bool readLine(char *s) {
  int c = getChar();
  while (c != '\n' && c != -1)
    *s++ = c, c = getChar();
  *s = 0;
  return c != -1;
}

static int write_buf_pos = 0;
static char write_buf[buf_size];

inline void writeChar( int x ) {
  if (write_buf_pos == buf_size)
    fwrite(write_buf, 1, buf_size, stdout), write_buf_pos = 0;
  write_buf[write_buf_pos++] = x;
}

inline void flush() {
  if (write_buf_pos) {
    fwrite(write_buf, 1, write_buf_pos, stdout), write_buf_pos = 0;
    fflush(stdout);
  }
}

template <class T>
inline void writeInt(T x, char end, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  char s[24];
  int n = 0;
  while (x || !n)
    s[n++] = '0' + x % 10, x /= 10;
  while (n < output_len)
    s[n++] = '0';
  while (n--)
    writeChar(s[n]);
  if (end)
    writeChar(end);
}

inline void writeWord(const char *s) {
  while (*s)
    writeChar(*s++);
}

inline void writeDouble(double x, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  int t = (int)x;
  writeInt(t), x -= t;
  writeChar('.');
  for (int i = output_len - 1; i > 0; i--) {
    x *= 10;
    t = std::min(9, (int)x);
    writeChar('0' + t), x -= t;
  }
  x *= 10;
  t = std::min(9, (int)(x + 0.5));
  writeChar('0' + t);
}

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")

using namespace std;

typedef long double ld;
typedef long long ll;

#define _ inline
#define f first
#define sec second
#define pb push_back
#define ins insert
#define ers erase
#define mk make_pair
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
//#define int ll

#define right rightt
#define left leftt
#define prev prevv
#define next nextt

mt19937 Random(time(0));

const int INF = 1e9 + 10;
const int MOD = 1e9 + 7;
const int P = 239017;
const long long BINF = 1e18 + 10;

struct SQRT_Decomposition {
  vector<int> L, L2, R, R2, T, arr;
  vector<unordered_map<int, int> > cnt;
  int n, cnt_blocks, len;
  SQRT_Decomposition(vector<int> _arr, int _n) {
    arr = _arr;
    n = _n;
    build();
  }
  void out() {
    for (auto it : T) {
      for (int i = L[it]; i <= R[it]; i++) {
        writeInt(arr[i], ' ');
      }
    }
    writeChar('\n');
  }
  void build() {
    cnt_blocks = (int)sqrt(n);
    len = n / cnt_blocks;
    if (cnt_blocks * len < n) {
      len++;
    }
    L.rsz(cnt_blocks);
    R.rsz(cnt_blocks);
    L2.rsz(cnt_blocks);
    R2.rsz(cnt_blocks);
    T.rsz(cnt_blocks);
    cnt.rsz(cnt_blocks);
    for (int i = 0; i < cnt_blocks; i++) {
      L[i] = len * i;
      R[i] = min(len * (i + 1), n) - 1;
      L2[i] = L[i], R2[i] = R[i];
      T[i] = i;
      for (int j = L[i]; j <= R[i]; j++) {
        cnt[i][arr[j]]++;
      }
    }
  }
  void rebuild() {
    vector<int> arr2;
    for (auto it : T) {
      for (int i = L[it]; i <= R[it]; i++) {
        arr2.pb(arr[i]);
      }
      arr = arr2;
      for (int i = 0; i < cnt_blocks; i++) {
        cnt[i].clear();
      }
      build();
    }
  }
  void create_new_block(int l, int r, int l2, int r2) {
    L.pb(l);
    R.pb(r);
    L2.pb(l2);
    R2.pb(r2);
    cnt.pb({});
    for (int i = l; i <= r; i++) {
      cnt[cnt_blocks][arr[i]]++;
    }
    cnt_blocks++;
  }
  void split(int x) {
    int ind = -1, pos = 0;
    for (auto it : T) {
      if (L2[it] <= x && R2[it] >= x) {
        ind = it;
        break;
      }
      pos++;
    }
    if (ind == -1 || R2[ind] == x) {
      return;
    }
    int ln = x - L2[ind];
    create_new_block(L[ind], L[ind] + ln, L2[ind], x);
    create_new_block(L[ind] + ln + 1, R[ind], x + 1, R2[ind]);
    vector<int> T2;
    for (int i = 0; i < pos; i++) {
      T2.pb(T[i]);
    }
    T2.pb(cnt_blocks - 2);
    T2.pb(cnt_blocks - 1);
    for (int i = pos + 1; i < (int)T.size(); i++) {
      T2.pb(T[i]);
    }
    T = T2;
  }
  void cut(int l, int r) {
    split(l - 1);
    split(r - 1);
    split(r);
    int pos1, pos2;
    for (int i = 0; i < (int)T.size(); i++) {
      if (L2[T[i]] == l) {
        pos1 = i;
      }
      if (R2[T[i]] == r) {
        pos2 = i;
      }
    }
    vector<int> T2;
    for (int i = 0; i < pos1; i++) {
      T2.pb(T[i]);
    }
    T2.pb(T[pos2]);
    for (int i = pos1; i < pos2; i++) {
      T2.pb(T[i]);
    }
    for (int i = pos2 + 1; i < (int)T.size(); i++) {
      T2.pb(T[i]);
    }
    T = T2;
    int cur = 0;
    for (auto it : T) {
      L2[it] = cur;
      R2[it] = cur + R[it] - L[it];
      cur = R2[it] + 1;
    }
  }
  int get(int l, int r, int k) {
    split(l - 1);
    split(r);
    int res = 0;
    for (auto it : T) {
      if (L2[it] >= l && R2[it] <= r) {
        res += cnt[it][k];
      }
    }
    return res;
  }
};

void source() {
  int n = readInt();
  vector<int> arr(n);
  for (auto &it : arr) {
    it = readInt();
  }
  SQRT_Decomposition A(arr, n);
  int m = readInt();
  int ans = 0;
  for (int i = 0; i < m; i++) {
    int type = readInt();
    if (type == 1) {
      int cur_l = readInt(), cur_r = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n;
      if (l > r) {
        swap(l, r);
      }
      A.cut(l, r);
    }
    else {
      int cur_l = readInt(), cur_r = readInt(), cur_k = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n, k = (cur_k + ans - 1) % n + 1;
      if (l > r) {
        swap(l, r);
      }
      ans = A.get(l, r, k);
      writeInt(ans, '\n');
    }
    //A.out();
  }
}

signed main() {
#ifdef EXTRATERRESTRIAL_
  assert(freopen("input.txt", "r", stdin));
  //assert(freopen("output.txt", "w", stdout));
#else
  //freopen(TASK".in", "r", stdin);
  //freopen(TASK".out", "w", stdout);
#endif
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  source();
  return 0;
}


#include <bits/stdc++.h>

#ifdef FAST_ALLOCATOR_MEMORY
int allocator_pos = 0;
char allocator_memory[(int)FAST_ALLOCATOR_MEMORY];
inline void * operator new ( size_t n ) {
  char *res = allocator_memory + allocator_pos;
  allocator_pos += n;
  assert(allocator_pos <= (int)FAST_ALLOCATOR_MEMORY);
  return (void *)res;
}
inline void operator delete ( void * ) noexcept { }
//inline void * operator new [] ( size_t ) { assert(0); }
//inline void operator delete [] ( void * ) { assert(0); }
#endif

template <class T = int> inline T readInt();
inline double readDouble();
inline int readUInt();
inline int readChar();
inline void readWord(char *s);
inline bool readLine(char *s);
inline bool isEof();
inline int getChar();
inline int peekChar();
inline bool seekEof();
inline void skipBlanks();

template <class T> inline void writeInt(T x, char end = 0, int len = -1);
inline void writeChar(int x);
inline void writeWord(const char *s);
inline void writeDouble(double x, int len = 0);
inline void flush();

static struct buffer_flusher_t {
  ~buffer_flusher_t() {
    flush();
  }
} buffer_flusher;

static const int buf_size = 4096;

static unsigned char buf[buf_size];
static int buf_len = 0, buf_pos = 0;

inline bool isEof() {
  if (buf_pos == buf_len) {
    buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
    if (buf_pos == buf_len)
      return 1;
  }
  return 0;
}

inline int getChar() {
  return isEof() ? -1 : buf[buf_pos++];
}

inline int peekChar() {
  return isEof() ? -1 : buf[buf_pos];
}

inline bool seekEof() {
  int c;
  while ((c = peekChar()) != -1 && c <= 32)
    buf_pos++;
  return c == -1;
}

inline void skipBlanks() {
  while (!isEof() && buf[buf_pos] <= 32U)
    buf_pos++;
}

inline int readChar() {
  int c = getChar();
  while (c != -1 && c <= 32)
    c = getChar();
  return c;
}

inline int readUInt() {
  int c = readChar(), x = 0;
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return x;
}

template <class T>
inline T readInt() {
  int s = 1, c = readChar();
  T x = 0;
  if (c == '-')
    s = -1, c = getChar();
  else if (c == '+')
    c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return s == 1 ? x : -x;
}

inline double readDouble() {
  int s = 1, c = readChar();
  double x = 0;
  if (c == '-')
    s = -1, c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  if (c == '.') {
    c = getChar();
    double coef = 1;
    while ('0' <= c && c <= '9')
      x += (c - '0') * (coef *= 1e-1), c = getChar();
  }
  return s == 1 ? x : -x;
}

inline void readWord(char *s) {
  int c = readChar();
  while (c > 32)
    *s++ = c, c = getChar();
  *s = 0;
}

inline bool readLine(char *s) {
  int c = getChar();
  while (c != '\n' && c != -1)
    *s++ = c, c = getChar();
  *s = 0;
  return c != -1;
}

static int write_buf_pos = 0;
static char write_buf[buf_size];

inline void writeChar( int x ) {
  if (write_buf_pos == buf_size)
    fwrite(write_buf, 1, buf_size, stdout), write_buf_pos = 0;
  write_buf[write_buf_pos++] = x;
}

inline void flush() {
  if (write_buf_pos) {
    fwrite(write_buf, 1, write_buf_pos, stdout), write_buf_pos = 0;
    fflush(stdout);
  }
}

template <class T>
inline void writeInt(T x, char end, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  char s[24];
  int n = 0;
  while (x || !n)
    s[n++] = '0' + x % 10, x /= 10;
  while (n < output_len)
    s[n++] = '0';
  while (n--)
    writeChar(s[n]);
  if (end)
    writeChar(end);
}

inline void writeWord(const char *s) {
  while (*s)
    writeChar(*s++);
}

inline void writeDouble(double x, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  int t = (int)x;
  writeInt(t), x -= t;
  writeChar('.');
  for (int i = output_len - 1; i > 0; i--) {
    x *= 10;
    t = std::min(9, (int)x);
    writeChar('0' + t), x -= t;
  }
  x *= 10;
  t = std::min(9, (int)(x + 0.5));
  writeChar('0' + t);
}

#pragma GCC optimize("Ofast")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("unswitch-loops")
#pragma GCC optimize("fast-math")
#pragma GCC optimize("section-anchors")
#pragma GCC optimize("profile-reorder-functions")
#pragma GCC optimize("profile-values")
#pragma GCC optimize("tracer")
#pragma GCC optimize("vpt")
#pragma GCC optimize("rename-registers")
#pragma GCC optimize("move-loop-invariants")
#pragma GCC optimize("function-sections")
#pragma GCC optimize("data-sections")
#pragma GCC optimize("branch-target-load-optimize")
#pragma GCC optimize("branch-target-load-optimize2")
#pragma GCC optimize("btr-bb-exclusive")
#pragma GCC target("sse2")
#pragma GCC target("sse3")
#pragma GCC target("ssse3")
#pragma GCC target("sse4.1")
#pragma GCC target("sse4.2")
#pragma GCC target("avx")
#pragma GCC target("avx2")
#pragma GCC target("popcnt")
#pragma GCC target("abm")
#pragma GCC target("mmx")
#pragma GCC target("tune=native")

using namespace std;

typedef long double ld;
typedef long long ll;

#define _ inline
#define f first
#define sec second
#define pb push_back
#define ins insert
#define ers erase
#define mk make_pair
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
//#define int ll

#define right rightt
#define left leftt
#define prev prevv
#define next nextt

mt19937 Random(time(0));

const int INF = 1e9 + 10;
const int MOD = 1e9 + 7;
const int P = 239017;
const long long BINF = 1e18 + 10;

const int R = 1200;
const int N = 1e5 + 10;
const int SZ = (int)sqrt(N);
int a[N], n, cur[SZ + 10][5 * SZ + 10], sz[SZ + 10], cnt_blocks;
short calc[SZ + 10][N];

inline void build() {
  cnt_blocks = 0;
  for (int i = 0; i < n; i += SZ) {
    int to = min(i + SZ, n) - 1;
    for (int j = i; j <= to; j++) {
      calc[cnt_blocks][a[j]]++;
      cur[cnt_blocks][sz[cnt_blocks]++] = a[j];
    }
    cnt_blocks++;
  }
}

inline void rebuild() {
  int ind = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    for (int j = 0; j < sz[i]; j++) {
      a[ind++] = cur[i][j];
      calc[i][cur[i][j]] = 0;
    }
    sz[i] = 0;
  }
  build();
}

inline int erase(int ind) {
  int sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > ind) {
      int ps = ind - sum, res = cur[i][ps];
      calc[i][res]--;
      for (int j = ps; j + 1 < sz[i]; j++) {
        cur[i][j] = cur[i][j + 1];
      }
      sz[i]--;
      return res;
    }
    sum += sz[i];
  }
  return 0;
}

inline void insert(int ind, int vl) {
  int sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > ind) {
      int ps = ind - sum + 1;
      calc[i][vl]++;
      sz[i]++;
      for (int j = sz[i] - 1; j > ps; j--) {
        cur[i][j] = cur[i][j - 1];
      }
      cur[i][ps] = vl;
      return;
    }
    sum += sz[i];
  }
  return;
}

inline void shift(int l, int r) {
  insert(l - 1, erase(r));
}

inline int get(int r, int vl) {
  int res = 0, sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > r) {
      int ps = r - sum;
      for (int j = 0; j <= ps; j++) {
        res += (cur[i][j] == vl);
      }
      break;
    }
    res += calc[i][vl];
    sum += sz[i];
  }
  return res;
}

void source() {
  n = readInt();
  for (int i = 0; i < n; i++) {
    a[i] = readInt();
  }
  int m = readInt();
  int ans = 0;
  for (int i = 0; i < m; i++) {
    if (i % R == 0) {
      rebuild();
    }
    int type = readInt();
    if (type == 1) {
      int cur_l = readInt(), cur_r = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n;
      if (l > r) {
        swap(l, r);
      }
      shift(l, r);
    }
    else {
      int cur_l = readInt(), cur_r = readInt(), cur_k = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n, k = (cur_k + ans - 1) % n + 1;
      if (l > r) {
        swap(l, r);
      }
      ans = get(r, k) - get(l - 1, k);
      writeInt(ans, '\n');
    }
  }
}

signed main() {
#ifdef extraterrestrial_
  assert(freopen("input.txt", "r", stdin));
  //assert(freopen("output.txt", "w", stdout));
#else
  //freopen(TASK".in", "r", stdin);
  //freopen(TASK".out", "w", stdout);
#endif
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  source();
  return 0;
}


#include <bits/stdc++.h>

#ifdef FAST_ALLOCATOR_MEMORY
int allocator_pos = 0;
char allocator_memory[(int)FAST_ALLOCATOR_MEMORY];
inline void * operator new ( size_t n ) {
  char *res = allocator_memory + allocator_pos;
  allocator_pos += n;
  assert(allocator_pos <= (int)FAST_ALLOCATOR_MEMORY);
  return (void *)res;
}
inline void operator delete ( void * ) noexcept { }
//inline void * operator new [] ( size_t ) { assert(0); }
//inline void operator delete [] ( void * ) { assert(0); }
#endif

template <class T = int> inline T readInt();
inline double readDouble();
inline int readUInt();
inline int readChar();
inline void readWord(char *s);
inline bool readLine(char *s);
inline bool isEof();
inline int getChar();
inline int peekChar();
inline bool seekEof();
inline void skipBlanks();

template <class T> inline void writeInt(T x, char end = 0, int len = -1);
inline void writeChar(int x);
inline void writeWord(const char *s);
inline void writeDouble(double x, int len = 0);
inline void flush();

static struct buffer_flusher_t {
  ~buffer_flusher_t() {
    flush();
  }
} buffer_flusher;

static const int buf_size = 4096;

static unsigned char buf[buf_size];
static int buf_len = 0, buf_pos = 0;

inline bool isEof() {
  if (buf_pos == buf_len) {
    buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
    if (buf_pos == buf_len)
      return 1;
  }
  return 0;
}

inline int getChar() {
  return isEof() ? -1 : buf[buf_pos++];
}

inline int peekChar() {
  return isEof() ? -1 : buf[buf_pos];
}

inline bool seekEof() {
  int c;
  while ((c = peekChar()) != -1 && c <= 32)
    buf_pos++;
  return c == -1;
}

inline void skipBlanks() {
  while (!isEof() && buf[buf_pos] <= 32U)
    buf_pos++;
}

inline int readChar() {
  int c = getChar();
  while (c != -1 && c <= 32)
    c = getChar();
  return c;
}

inline int readUInt() {
  int c = readChar(), x = 0;
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return x;
}

template <class T>
inline T readInt() {
  int s = 1, c = readChar();
  T x = 0;
  if (c == '-')
    s = -1, c = getChar();
  else if (c == '+')
    c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return s == 1 ? x : -x;
}

inline double readDouble() {
  int s = 1, c = readChar();
  double x = 0;
  if (c == '-')
    s = -1, c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  if (c == '.') {
    c = getChar();
    double coef = 1;
    while ('0' <= c && c <= '9')
      x += (c - '0') * (coef *= 1e-1), c = getChar();
  }
  return s == 1 ? x : -x;
}

inline void readWord(char *s) {
  int c = readChar();
  while (c > 32)
    *s++ = c, c = getChar();
  *s = 0;
}

inline bool readLine(char *s) {
  int c = getChar();
  while (c != '\n' && c != -1)
    *s++ = c, c = getChar();
  *s = 0;
  return c != -1;
}

static int write_buf_pos = 0;
static char write_buf[buf_size];

inline void writeChar( int x ) {
  if (write_buf_pos == buf_size)
    fwrite(write_buf, 1, buf_size, stdout), write_buf_pos = 0;
  write_buf[write_buf_pos++] = x;
}

inline void flush() {
  if (write_buf_pos) {
    fwrite(write_buf, 1, write_buf_pos, stdout), write_buf_pos = 0;
    fflush(stdout);
  }
}

template <class T>
inline void writeInt(T x, char end, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  char s[24];
  int n = 0;
  while (x || !n)
    s[n++] = '0' + x % 10, x /= 10;
  while (n < output_len)
    s[n++] = '0';
  while (n--)
    writeChar(s[n]);
  if (end)
    writeChar(end);
}

inline void writeWord(const char *s) {
  while (*s)
    writeChar(*s++);
}

inline void writeDouble(double x, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  int t = (int)x;
  writeInt(t), x -= t;
  writeChar('.');
  for (int i = output_len - 1; i > 0; i--) {
    x *= 10;
    t = std::min(9, (int)x);
    writeChar('0' + t), x -= t;
  }
  x *= 10;
  t = std::min(9, (int)(x + 0.5));
  writeChar('0' + t);
}

#pragma GCC optimize("Ofast")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("unswitch-loops")
#pragma GCC optimize("fast-math")
#pragma GCC optimize("section-anchors")
#pragma GCC optimize("profile-reorder-functions")
#pragma GCC optimize("profile-values")
#pragma GCC optimize("tracer")
#pragma GCC optimize("vpt")
#pragma GCC optimize("rename-registers")
#pragma GCC optimize("move-loop-invariants")
#pragma GCC optimize("function-sections")
#pragma GCC optimize("data-sections")
#pragma GCC optimize("branch-target-load-optimize")
#pragma GCC optimize("branch-target-load-optimize2")
#pragma GCC optimize("btr-bb-exclusive")
#pragma GCC target("sse2")
#pragma GCC target("sse3")
#pragma GCC target("ssse3")
#pragma GCC target("sse4.1")
#pragma GCC target("sse4.2")
#pragma GCC target("avx")
#pragma GCC target("avx2")
#pragma GCC target("popcnt")
#pragma GCC target("abm")
#pragma GCC target("mmx")
#pragma GCC target("tune=native")

using namespace std;

typedef long double ld;
typedef long long ll;

#define _ inline
#define f first
#define sec second
#define pb push_back
#define ins insert
#define ers erase
#define mk make_pair
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
//#define int ll

#define right rightt
#define left leftt
#define prev prevv
#define next nextt

mt19937 Random(time(0));

const int INF = 1e9 + 10;
const int MOD = 1e9 + 7;
const int P = 239017;
const long long BINF = 1e18 + 10;

const int R = 1050;
const int N = 1e5 + 10;
const int SZ = (int)sqrt(N);
int a[N], n, cur[SZ + 10][5 * SZ + 10], sz[SZ + 10], cnt_blocks;
short calc[SZ + 10][N];

inline void build() {
  cnt_blocks = 0;
  for (int i = 0; i < n; i += SZ) {
    int to = min(i + SZ, n) - 1;
    for (int j = i; j <= to; j++) {
      calc[cnt_blocks][a[j]]++;
      cur[cnt_blocks][sz[cnt_blocks]++] = a[j];
    }
    cnt_blocks++;
  }
}

inline void rebuild() {
  int ind = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    for (int j = 0; j < sz[i]; j++) {
      a[ind++] = cur[i][j];
      calc[i][cur[i][j]] = 0;
    }
    sz[i] = 0;
  }
  build();
}

inline int erase(int ind) {
  int sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > ind) {
      int ps = ind - sum, res = cur[i][ps];
      calc[i][res]--;
      for (int j = ps; j + 1 < sz[i]; j++) {
        cur[i][j] = cur[i][j + 1];
      }
      sz[i]--;
      return res;
    }
    sum += sz[i];
  }
  return 0;
}

inline void insert(int ind, int vl) {
  int sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > ind) {
      int ps = ind - sum + 1;
      calc[i][vl]++;
      sz[i]++;
      for (int j = sz[i] - 1; j > ps; j--) {
        cur[i][j] = cur[i][j - 1];
      }
      cur[i][ps] = vl;
      return;
    }
    sum += sz[i];
  }
  return;
}

inline void shift(int l, int r) {
  insert(l - 1, erase(r));
}

inline int get(int r, int vl) {
  int res = 0, sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > r) {
      int ps = r - sum;
      for (int j = 0; j <= ps; j++) {
        res += (cur[i][j] == vl);
      }
      break;
    }
    res += calc[i][vl];
    sum += sz[i];
  }
  return res;
}

void source() {
  n = readInt();
  for (int i = 0; i < n; i++) {
    a[i] = readInt();
  }
  int m = readInt();
  int ans = 0;
  for (int i = 0; i < m; i++) {
    if (i % R == 0) {
      rebuild();
    }
    int type = readInt();
    if (type == 1) {
      int cur_l = readInt(), cur_r = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n;
      if (l > r) {
        swap(l, r);
      }
      shift(l, r);
    }
    else {
      int cur_l = readInt(), cur_r = readInt(), cur_k = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n, k = (cur_k + ans - 1) % n + 1;
      if (l > r) {
        swap(l, r);
      }
      ans = get(r, k) - get(l - 1, k);
      writeInt(ans, '\n');
    }
  }
}

signed main() {
#ifdef extraterrestrial_
  assert(freopen("input.txt", "r", stdin));
  //assert(freopen("output.txt", "w", stdout));
#else
  //freopen(TASK".in", "r", stdin);
  //freopen(TASK".out", "w", stdout);
#endif
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  source();
  return 0;
}


#include <bits/stdc++.h>

#ifdef FAST_ALLOCATOR_MEMORY
int allocator_pos = 0;
char allocator_memory[(int)FAST_ALLOCATOR_MEMORY];
inline void * operator new ( size_t n ) {
  char *res = allocator_memory + allocator_pos;
  allocator_pos += n;
  assert(allocator_pos <= (int)FAST_ALLOCATOR_MEMORY);
  return (void *)res;
}
inline void operator delete ( void * ) noexcept { }
//inline void * operator new [] ( size_t ) { assert(0); }
//inline void operator delete [] ( void * ) { assert(0); }
#endif

template <class T = int> inline T readInt();
inline double readDouble();
inline int readUInt();
inline int readChar();
inline void readWord(char *s);
inline bool readLine(char *s);
inline bool isEof();
inline int getChar();
inline int peekChar();
inline bool seekEof();
inline void skipBlanks();

template <class T> inline void writeInt(T x, char end = 0, int len = -1);
inline void writeChar(int x);
inline void writeWord(const char *s);
inline void writeDouble(double x, int len = 0);
inline void flush();

static struct buffer_flusher_t {
  ~buffer_flusher_t() {
    flush();
  }
} buffer_flusher;

static const int buf_size = 4096;

static unsigned char buf[buf_size];
static int buf_len = 0, buf_pos = 0;

inline bool isEof() {
  if (buf_pos == buf_len) {
    buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
    if (buf_pos == buf_len)
      return 1;
  }
  return 0;
}

inline int getChar() {
  return isEof() ? -1 : buf[buf_pos++];
}

inline int peekChar() {
  return isEof() ? -1 : buf[buf_pos];
}

inline bool seekEof() {
  int c;
  while ((c = peekChar()) != -1 && c <= 32)
    buf_pos++;
  return c == -1;
}

inline void skipBlanks() {
  while (!isEof() && buf[buf_pos] <= 32U)
    buf_pos++;
}

inline int readChar() {
  int c = getChar();
  while (c != -1 && c <= 32)
    c = getChar();
  return c;
}

inline int readUInt() {
  int c = readChar(), x = 0;
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return x;
}

template <class T>
inline T readInt() {
  int s = 1, c = readChar();
  T x = 0;
  if (c == '-')
    s = -1, c = getChar();
  else if (c == '+')
    c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return s == 1 ? x : -x;
}

inline double readDouble() {
  int s = 1, c = readChar();
  double x = 0;
  if (c == '-')
    s = -1, c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  if (c == '.') {
    c = getChar();
    double coef = 1;
    while ('0' <= c && c <= '9')
      x += (c - '0') * (coef *= 1e-1), c = getChar();
  }
  return s == 1 ? x : -x;
}

inline void readWord(char *s) {
  int c = readChar();
  while (c > 32)
    *s++ = c, c = getChar();
  *s = 0;
}

inline bool readLine(char *s) {
  int c = getChar();
  while (c != '\n' && c != -1)
    *s++ = c, c = getChar();
  *s = 0;
  return c != -1;
}

static int write_buf_pos = 0;
static char write_buf[buf_size];

inline void writeChar( int x ) {
  if (write_buf_pos == buf_size)
    fwrite(write_buf, 1, buf_size, stdout), write_buf_pos = 0;
  write_buf[write_buf_pos++] = x;
}

inline void flush() {
  if (write_buf_pos) {
    fwrite(write_buf, 1, write_buf_pos, stdout), write_buf_pos = 0;
    fflush(stdout);
  }
}

template <class T>
inline void writeInt(T x, char end, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  char s[24];
  int n = 0;
  while (x || !n)
    s[n++] = '0' + x % 10, x /= 10;
  while (n < output_len)
    s[n++] = '0';
  while (n--)
    writeChar(s[n]);
  if (end)
    writeChar(end);
}

inline void writeWord(const char *s) {
  while (*s)
    writeChar(*s++);
}

inline void writeDouble(double x, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  int t = (int)x;
  writeInt(t), x -= t;
  writeChar('.');
  for (int i = output_len - 1; i > 0; i--) {
    x *= 10;
    t = std::min(9, (int)x);
    writeChar('0' + t), x -= t;
  }
  x *= 10;
  t = std::min(9, (int)(x + 0.5));
  writeChar('0' + t);
}

#pragma GCC optimize("Ofast")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("unswitch-loops")
#pragma GCC optimize("fast-math")
#pragma GCC optimize("section-anchors")
#pragma GCC optimize("profile-reorder-functions")
#pragma GCC optimize("profile-values")
#pragma GCC optimize("tracer")
#pragma GCC optimize("vpt")
#pragma GCC optimize("rename-registers")
#pragma GCC optimize("move-loop-invariants")
#pragma GCC optimize("function-sections")
#pragma GCC optimize("data-sections")
#pragma GCC optimize("branch-target-load-optimize")
#pragma GCC optimize("branch-target-load-optimize2")
#pragma GCC optimize("btr-bb-exclusive")
#pragma GCC target("sse2")
#pragma GCC target("sse3")
#pragma GCC target("ssse3")
#pragma GCC target("sse4.1")
#pragma GCC target("sse4.2")
#pragma GCC target("avx")
#pragma GCC target("avx2")
#pragma GCC target("popcnt")
#pragma GCC target("abm")
#pragma GCC target("mmx")
#pragma GCC target("tune=native")

using namespace std;

typedef long double ld;
typedef long long ll;

#define _ inline
#define f first
#define sec second
#define pb push_back
#define ins insert
#define ers erase
#define mk make_pair
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
//#define int ll

#define right rightt
#define left leftt
#define prev prevv
#define next nextt

mt19937 Random(time(0));

const int INF = 1e9 + 10;
const int MOD = 1e9 + 7;
const int P = 239017;
const long long BINF = 1e18 + 10;

const int R = 1000;
const int N = 1e5 + 10;
const int SZ = 250;
int a[N], n, cur[SZ + 10][10 * SZ + 10], sz[SZ + 10], cnt_blocks;
short calc[SZ + 10][N];

inline void build() {
  cnt_blocks = 0;
  for (int i = 0; i < n; i += SZ) {
    int to = min(i + SZ, n) - 1;
    for (int j = i; j <= to; j++) {
      calc[cnt_blocks][a[j]]++;
      cur[cnt_blocks][sz[cnt_blocks]++] = a[j];
    }
    cnt_blocks++;
  }
}

inline void rebuild() {
  int ind = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    for (int j = 0; j < sz[i]; j++) {
      a[ind++] = cur[i][j];
      calc[i][cur[i][j]] = 0;
    }
    sz[i] = 0;
  }
  build();
}

inline int erase(int ind) {
  int sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > ind) {
      int ps = ind - sum, res = cur[i][ps];
      calc[i][res]--;
      for (int j = ps; j + 1 < sz[i]; j++) {
        cur[i][j] = cur[i][j + 1];
      }
      sz[i]--;
      return res;
    }
    sum += sz[i];
  }
  return 0;
}

inline void insert(int ind, int vl) {
  int sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > ind) {
      int ps = ind - sum + 1;
      calc[i][vl]++;
      sz[i]++;
      for (int j = sz[i] - 1; j > ps; j--) {
        cur[i][j] = cur[i][j - 1];
      }
      cur[i][ps] = vl;
      return;
    }
    sum += sz[i];
  }
  return;
}

inline void shift(int l, int r) {
  insert(l - 1, erase(r));
}

inline int get(int r, int vl) {
  int res = 0, sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > r) {
      int ps = r - sum;
      for (int j = 0; j <= ps; j++) {
        res += (cur[i][j] == vl);
      }
      break;
    }
    res += calc[i][vl];
    sum += sz[i];
  }
  return res;
}

void source() {
  n = readInt();
  for (int i = 0; i < n; i++) {
    a[i] = readInt();
  }
  int m = readInt();
  int ans = 0;
  for (int i = 0; i < m; i++) {
    if (i % R == 0) {
      rebuild();
    }
    int type = readInt();
    if (type == 1) {
      int cur_l = readInt(), cur_r = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n;
      if (l > r) {
        swap(l, r);
      }
      shift(l, r);
    }
    else {
      int cur_l = readInt(), cur_r = readInt(), cur_k = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n, k = (cur_k + ans - 1) % n + 1;
      if (l > r) {
        swap(l, r);
      }
      ans = get(r, k) - get(l - 1, k);
      writeInt(ans, '\n');
    }
  }
}

signed main() {
#ifdef extraterrestrial_
  assert(freopen("input.txt", "r", stdin));
  //assert(freopen("output.txt", "w", stdout));
#else
  //freopen(TASK".in", "r", stdin);
  //freopen(TASK".out", "w", stdout);
#endif
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  source();
  return 0;
}


#include <bits/stdc++.h>

#ifdef FAST_ALLOCATOR_MEMORY
int allocator_pos = 0;
char allocator_memory[(int)FAST_ALLOCATOR_MEMORY];
inline void * operator new ( size_t n ) {
  char *res = allocator_memory + allocator_pos;
  allocator_pos += n;
  assert(allocator_pos <= (int)FAST_ALLOCATOR_MEMORY);
  return (void *)res;
}
inline void operator delete ( void * ) noexcept { }
//inline void * operator new [] ( size_t ) { assert(0); }
//inline void operator delete [] ( void * ) { assert(0); }
#endif

template <class T = int> inline T readInt();
inline double readDouble();
inline int readUInt();
inline int readChar();
inline void readWord(char *s);
inline bool readLine(char *s);
inline bool isEof();
inline int getChar();
inline int peekChar();
inline bool seekEof();
inline void skipBlanks();

template <class T> inline void writeInt(T x, char end = 0, int len = -1);
inline void writeChar(int x);
inline void writeWord(const char *s);
inline void writeDouble(double x, int len = 0);
inline void flush();

static struct buffer_flusher_t {
  ~buffer_flusher_t() {
    flush();
  }
} buffer_flusher;

static const int buf_size = 4096;

static unsigned char buf[buf_size];
static int buf_len = 0, buf_pos = 0;

inline bool isEof() {
  if (buf_pos == buf_len) {
    buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
    if (buf_pos == buf_len)
      return 1;
  }
  return 0;
}

inline int getChar() {
  return isEof() ? -1 : buf[buf_pos++];
}

inline int peekChar() {
  return isEof() ? -1 : buf[buf_pos];
}

inline bool seekEof() {
  int c;
  while ((c = peekChar()) != -1 && c <= 32)
    buf_pos++;
  return c == -1;
}

inline void skipBlanks() {
  while (!isEof() && buf[buf_pos] <= 32U)
    buf_pos++;
}

inline int readChar() {
  int c = getChar();
  while (c != -1 && c <= 32)
    c = getChar();
  return c;
}

inline int readUInt() {
  int c = readChar(), x = 0;
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return x;
}

template <class T>
inline T readInt() {
  int s = 1, c = readChar();
  T x = 0;
  if (c == '-')
    s = -1, c = getChar();
  else if (c == '+')
    c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return s == 1 ? x : -x;
}

inline double readDouble() {
  int s = 1, c = readChar();
  double x = 0;
  if (c == '-')
    s = -1, c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  if (c == '.') {
    c = getChar();
    double coef = 1;
    while ('0' <= c && c <= '9')
      x += (c - '0') * (coef *= 1e-1), c = getChar();
  }
  return s == 1 ? x : -x;
}

inline void readWord(char *s) {
  int c = readChar();
  while (c > 32)
    *s++ = c, c = getChar();
  *s = 0;
}

inline bool readLine(char *s) {
  int c = getChar();
  while (c != '\n' && c != -1)
    *s++ = c, c = getChar();
  *s = 0;
  return c != -1;
}

static int write_buf_pos = 0;
static char write_buf[buf_size];

inline void writeChar( int x ) {
  if (write_buf_pos == buf_size)
    fwrite(write_buf, 1, buf_size, stdout), write_buf_pos = 0;
  write_buf[write_buf_pos++] = x;
}

inline void flush() {
  if (write_buf_pos) {
    fwrite(write_buf, 1, write_buf_pos, stdout), write_buf_pos = 0;
    fflush(stdout);
  }
}

template <class T>
inline void writeInt(T x, char end, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  char s[24];
  int n = 0;
  while (x || !n)
    s[n++] = '0' + x % 10, x /= 10;
  while (n < output_len)
    s[n++] = '0';
  while (n--)
    writeChar(s[n]);
  if (end)
    writeChar(end);
}

inline void writeWord(const char *s) {
  while (*s)
    writeChar(*s++);
}

inline void writeDouble(double x, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  int t = (int)x;
  writeInt(t), x -= t;
  writeChar('.');
  for (int i = output_len - 1; i > 0; i--) {
    x *= 10;
    t = std::min(9, (int)x);
    writeChar('0' + t), x -= t;
  }
  x *= 10;
  t = std::min(9, (int)(x + 0.5));
  writeChar('0' + t);
}

#pragma GCC optimize("Ofast")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("unswitch-loops")
#pragma GCC optimize("fast-math")
#pragma GCC optimize("section-anchors")
#pragma GCC optimize("profile-reorder-functions")
#pragma GCC optimize("profile-values")
#pragma GCC optimize("tracer")
#pragma GCC optimize("vpt")
#pragma GCC optimize("rename-registers")
#pragma GCC optimize("move-loop-invariants")
#pragma GCC optimize("function-sections")
#pragma GCC optimize("data-sections")
#pragma GCC optimize("branch-target-load-optimize")
#pragma GCC optimize("branch-target-load-optimize2")
#pragma GCC optimize("btr-bb-exclusive")
#pragma GCC target("sse2")
#pragma GCC target("sse3")
#pragma GCC target("ssse3")
#pragma GCC target("sse4.1")
#pragma GCC target("sse4.2")
#pragma GCC target("avx")
#pragma GCC target("avx2")
#pragma GCC target("popcnt")
#pragma GCC target("abm")
#pragma GCC target("mmx")
#pragma GCC target("tune=native")

using namespace std;

typedef long double ld;
typedef long long ll;

#define _ inline
#define f first
#define sec second
#define pb push_back
#define ins insert
#define ers erase
#define mk make_pair
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
//#define int ll

#define right rightt
#define left leftt
#define prev prevv
#define next nextt

mt19937 Random(time(0));

const int INF = 1e9 + 10;
const int MOD = 1e9 + 7;
const int P = 239017;
const long long BINF = 1e18 + 10;

const int R = 950;
const int N = 1e5 + 10;
const int SZ = (int)sqrt(N);
int a[N], n, cur[SZ + 10][5 * SZ + 10], sz[SZ + 10], cnt_blocks;
short calc[SZ + 10][N];

inline void build() {
  cnt_blocks = 0;
  for (int i = 0; i < n; i += SZ) {
    int to = min(i + SZ, n) - 1;
    for (int j = i; j <= to; j++) {
      calc[cnt_blocks][a[j]]++;
      cur[cnt_blocks][sz[cnt_blocks]++] = a[j];
    }
    cnt_blocks++;
  }
}

inline void rebuild() {
  int ind = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    for (int j = 0; j < sz[i]; j++) {
      a[ind++] = cur[i][j];
      calc[i][cur[i][j]] = 0;
    }
    sz[i] = 0;
  }
  build();
}

inline int erase(int ind) {
  int sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > ind) {
      int ps = ind - sum, res = cur[i][ps];
      calc[i][res]--;
      for (int j = ps; j + 1 < sz[i]; j++) {
        cur[i][j] = cur[i][j + 1];
      }
      sz[i]--;
      return res;
    }
    sum += sz[i];
  }
  return 0;
}

inline void insert(int ind, int vl) {
  int sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > ind) {
      int ps = ind - sum + 1;
      calc[i][vl]++;
      sz[i]++;
      for (int j = sz[i] - 1; j > ps; j--) {
        cur[i][j] = cur[i][j - 1];
      }
      cur[i][ps] = vl;
      return;
    }
    sum += sz[i];
  }
  return;
}

inline void shift(int l, int r) {
  insert(l - 1, erase(r));
}

inline int get(int r, int vl) {
  int res = 0, sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > r) {
      int ps = r - sum;
      for (int j = 0; j <= ps; j++) {
        res += (cur[i][j] == vl);
      }
      break;
    }
    res += calc[i][vl];
    sum += sz[i];
  }
  return res;
}

void source() {
  n = readInt();
  for (int i = 0; i < n; i++) {
    a[i] = readInt();
  }
  int m = readInt();
  int ans = 0;
  for (int i = 0; i < m; i++) {
    if (i % R == 0) {
      rebuild();
    }
    int type = readInt();
    if (type == 1) {
      int cur_l = readInt(), cur_r = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n;
      if (l > r) {
        swap(l, r);
      }
      shift(l, r);
    }
    else {
      int cur_l = readInt(), cur_r = readInt(), cur_k = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n, k = (cur_k + ans - 1) % n + 1;
      if (l > r) {
        swap(l, r);
      }
      ans = get(r, k) - get(l - 1, k);
      writeInt(ans, '\n');
    }
  }
}

signed main() {
#ifdef extraterrestrial_
  assert(freopen("input.txt", "r", stdin));
  //assert(freopen("output.txt", "w", stdout));
#else
  //freopen(TASK".in", "r", stdin);
  //freopen(TASK".out", "w", stdout);
#endif
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  source();
  return 0;
}


#include <bits/stdc++.h>

#ifdef FAST_ALLOCATOR_MEMORY
int allocator_pos = 0;
char allocator_memory[(int)FAST_ALLOCATOR_MEMORY];
inline void * operator new ( size_t n ) {
  char *res = allocator_memory + allocator_pos;
  allocator_pos += n;
  assert(allocator_pos <= (int)FAST_ALLOCATOR_MEMORY);
  return (void *)res;
}
inline void operator delete ( void * ) noexcept { }
//inline void * operator new [] ( size_t ) { assert(0); }
//inline void operator delete [] ( void * ) { assert(0); }
#endif

template <class T = int> inline T readInt();
inline double readDouble();
inline int readUInt();
inline int readChar();
inline void readWord(char *s);
inline bool readLine(char *s);
inline bool isEof();
inline int getChar();
inline int peekChar();
inline bool seekEof();
inline void skipBlanks();

template <class T> inline void writeInt(T x, char end = 0, int len = -1);
inline void writeChar(int x);
inline void writeWord(const char *s);
inline void writeDouble(double x, int len = 0);
inline void flush();

static struct buffer_flusher_t {
  ~buffer_flusher_t() {
    flush();
  }
} buffer_flusher;

static const int buf_size = 4096;

static unsigned char buf[buf_size];
static int buf_len = 0, buf_pos = 0;

inline bool isEof() {
  if (buf_pos == buf_len) {
    buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
    if (buf_pos == buf_len)
      return 1;
  }
  return 0;
}

inline int getChar() {
  return isEof() ? -1 : buf[buf_pos++];
}

inline int peekChar() {
  return isEof() ? -1 : buf[buf_pos];
}

inline bool seekEof() {
  int c;
  while ((c = peekChar()) != -1 && c <= 32)
    buf_pos++;
  return c == -1;
}

inline void skipBlanks() {
  while (!isEof() && buf[buf_pos] <= 32U)
    buf_pos++;
}

inline int readChar() {
  int c = getChar();
  while (c != -1 && c <= 32)
    c = getChar();
  return c;
}

inline int readUInt() {
  int c = readChar(), x = 0;
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return x;
}

template <class T>
inline T readInt() {
  int s = 1, c = readChar();
  T x = 0;
  if (c == '-')
    s = -1, c = getChar();
  else if (c == '+')
    c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return s == 1 ? x : -x;
}

inline double readDouble() {
  int s = 1, c = readChar();
  double x = 0;
  if (c == '-')
    s = -1, c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  if (c == '.') {
    c = getChar();
    double coef = 1;
    while ('0' <= c && c <= '9')
      x += (c - '0') * (coef *= 1e-1), c = getChar();
  }
  return s == 1 ? x : -x;
}

inline void readWord(char *s) {
  int c = readChar();
  while (c > 32)
    *s++ = c, c = getChar();
  *s = 0;
}

inline bool readLine(char *s) {
  int c = getChar();
  while (c != '\n' && c != -1)
    *s++ = c, c = getChar();
  *s = 0;
  return c != -1;
}

static int write_buf_pos = 0;
static char write_buf[buf_size];

inline void writeChar( int x ) {
  if (write_buf_pos == buf_size)
    fwrite(write_buf, 1, buf_size, stdout), write_buf_pos = 0;
  write_buf[write_buf_pos++] = x;
}

inline void flush() {
  if (write_buf_pos) {
    fwrite(write_buf, 1, write_buf_pos, stdout), write_buf_pos = 0;
    fflush(stdout);
  }
}

template <class T>
inline void writeInt(T x, char end, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  char s[24];
  int n = 0;
  while (x || !n)
    s[n++] = '0' + x % 10, x /= 10;
  while (n < output_len)
    s[n++] = '0';
  while (n--)
    writeChar(s[n]);
  if (end)
    writeChar(end);
}

inline void writeWord(const char *s) {
  while (*s)
    writeChar(*s++);
}

inline void writeDouble(double x, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  int t = (int)x;
  writeInt(t), x -= t;
  writeChar('.');
  for (int i = output_len - 1; i > 0; i--) {
    x *= 10;
    t = std::min(9, (int)x);
    writeChar('0' + t), x -= t;
  }
  x *= 10;
  t = std::min(9, (int)(x + 0.5));
  writeChar('0' + t);
}

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")

using namespace std;

typedef long double ld;
typedef long long ll;

#define _ inline
#define f first
#define sec second
#define pb push_back
#define ins insert
#define ers erase
#define mk make_pair
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
//#define int ll

#define right rightt
#define left leftt
#define prev prevv
#define next nextt

mt19937 Random(time(0));

const int INF = 1e9 + 10;
const int MOD = 1e9 + 7;
const int P = 239017;
const long long BINF = 1e18 + 10;

const int R = 400;
const int N = 1e5 + 10;
const int SZ = (int)sqrt(N);
int a[N], n, cur[SZ + 10][SZ + 10], sz[SZ + 10], cnt_blocks;
short calc[SZ + 10][N];

inline void build() {
  cnt_blocks = 0;
  for (int i = 0; i < n; i += SZ) {
    int to = min(i + SZ, n) - 1;
    for (int j = i; j <= to; j++) {
      calc[cnt_blocks][a[j]]++;
      cur[cnt_blocks][sz[cnt_blocks]++] = a[j];
    }
    cnt_blocks++;
  }
}

inline void rebuild() {
  int ind = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    for (int j = 0; j < sz[i]; j++) {
      a[ind++] = cur[i][j];
      calc[i][cur[i][j]] = 0;
    }
  }
  build();
}

inline int erase(int ind) {
  int sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > ind) {
      int ps = ind - sum, res = cur[i][ps];
      calc[i][res]--;
      for (int j = ps; j + 1 < sz[i]; j++) {
        cur[i][j] = cur[i][j + 1];
      }
      sz[i]--;
      return res;
    }
    sum += sz[i];
  }
  return 0;
}

inline void insert(int ind, int vl) {
  int sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > ind) {
      int ps = ind - sum + 1;
      calc[i][vl]++;
      sz[i]++;
      for (int j = sz[i] - 1; j > ps; j--) {
        cur[i][j] = cur[i][j - 1];
      }
      cur[i][ps] = vl;
      return;
    }
    sum += sz[i];
  }
  return;
}

inline void shift(int l, int r) {
  insert(l - 1, erase(r));
}

inline int get(int r, int vl) {
  int res = 0, sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > r) {
      int ps = r - sum;
      for (int j = 0; j <= ps; j++) {
        res += (cur[i][j] == vl);
      }
      break;
    }
    res += calc[i][vl];
    sum += sz[i];
  }
  return res;
}

void source() {
  n = readInt();
  for (int i = 0; i < n; i++) {
    a[i] = readInt();
  }
  int m = readInt();
  int ans = 0;
  for (int i = 0; i < m; i++) {
    if (i % R == 0) {
      rebuild();
    }
    int type = readInt();
    if (type == 1) {
      int cur_l = readInt(), cur_r = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n;
      if (l > r) {
        swap(l, r);
      }
      shift(l, r);
    }
    else {
      int cur_l = readInt(), cur_r = readInt(), cur_k = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n, k = (cur_k + ans - 1) % n + 1;
      if (l > r) {
        swap(l, r);
      }
      ans = get(r, k) - get(l - 1, k);
      writeInt(ans, '\n');
    }
  }
}

signed main() {
#ifdef extraterrestrial_
  assert(freopen("input.txt", "r", stdin));
  //assert(freopen("output.txt", "w", stdout));
#else
  //freopen(TASK".in", "r", stdin);
  //freopen(TASK".out", "w", stdout);
#endif
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  source();
  return 0;
}


//I_l_M_P
#include <bits/stdc++.h>

#define FAST_ALLOCATOR_MEMORY 2e8

#ifdef FAST_ALLOCATOR_MEMORY
int allocator_pos = 0;
char allocator_memory[(int)FAST_ALLOCATOR_MEMORY];
inline void * operator new ( size_t n ) {
  char *res = allocator_memory + allocator_pos;
  allocator_pos += n;
  assert(allocator_pos <= (int)FAST_ALLOCATOR_MEMORY);
  return (void *)res;
}
inline void operator delete ( void * ) noexcept { }
//inline void * operator new [] ( size_t ) { assert(0); }
//inline void operator delete [] ( void * ) { assert(0); }
#endif

template <class T = int> inline T readInt();
inline double readDouble();
inline int readUInt();
inline int readChar();
inline void readWord(char *s);
inline bool readLine(char *s);
inline bool isEof();
inline int getChar();
inline int peekChar();
inline bool seekEof();
inline void skipBlanks();

template <class T> inline void writeInt(T x, char end = 0, int len = -1);
inline void writeChar(int x);
inline void writeWord(const char *s);
inline void writeDouble(double x, int len = 0);
inline void flush();

static struct buffer_flusher_t {
  ~buffer_flusher_t() {
    flush();
  }
} buffer_flusher;

static const int buf_size = 4096;

static unsigned char buf[buf_size];
static int buf_len = 0, buf_pos = 0;

inline bool isEof() {
  if (buf_pos == buf_len) {
    buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
    if (buf_pos == buf_len)
      return 1;
  }
  return 0;
}

inline int getChar() {
  return isEof() ? -1 : buf[buf_pos++];
}

inline int peekChar() {
  return isEof() ? -1 : buf[buf_pos];
}

inline bool seekEof() {
  int c;
  while ((c = peekChar()) != -1 && c <= 32)
    buf_pos++;
  return c == -1;
}

inline void skipBlanks() {
  while (!isEof() && buf[buf_pos] <= 32U)
    buf_pos++;
}

inline int readChar() {
  int c = getChar();
  while (c != -1 && c <= 32)
    c = getChar();
  return c;
}

inline int readUInt() {
  int c = readChar(), x = 0;
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return x;
}

template <class T>
inline T readInt() {
  int s = 1, c = readChar();
  T x = 0;
  if (c == '-')
    s = -1, c = getChar();
  else if (c == '+')
    c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return s == 1 ? x : -x;
}

inline double readDouble() {
  int s = 1, c = readChar();
  double x = 0;
  if (c == '-')
    s = -1, c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  if (c == '.') {
    c = getChar();
    double coef = 1;
    while ('0' <= c && c <= '9')
      x += (c - '0') * (coef *= 1e-1), c = getChar();
  }
  return s == 1 ? x : -x;
}

inline void readWord(char *s) {
  int c = readChar();
  while (c > 32)
    *s++ = c, c = getChar();
  *s = 0;
}

inline bool readLine(char *s) {
  int c = getChar();
  while (c != '\n' && c != -1)
    *s++ = c, c = getChar();
  *s = 0;
  return c != -1;
}

static int write_buf_pos = 0;
static char write_buf[buf_size];

inline void writeChar( int x ) {
  if (write_buf_pos == buf_size)
    fwrite(write_buf, 1, buf_size, stdout), write_buf_pos = 0;
  write_buf[write_buf_pos++] = x;
}

inline void flush() {
  if (write_buf_pos) {
    fwrite(write_buf, 1, write_buf_pos, stdout), write_buf_pos = 0;
    fflush(stdout);
  }
}

template <class T>
inline void writeInt(T x, char end, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  char s[24];
  int n = 0;
  while (x || !n)
    s[n++] = '0' + x % 10, x /= 10;
  while (n < output_len)
    s[n++] = '0';
  while (n--)
    writeChar(s[n]);
  if (end)
    writeChar(end);
}

inline void writeWord(const char *s) {
  while (*s)
    writeChar(*s++);
}

inline void writeDouble(double x, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  int t = (int)x;
  writeInt(t), x -= t;
  writeChar('.');
  for (int i = output_len - 1; i > 0; i--) {
    x *= 10;
    t = std::min(9, (int)x);
    writeChar('0' + t), x -= t;
  }
  x *= 10;
  t = std::min(9, (int)(x + 0.5));
  writeChar('0' + t);
}

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")

using namespace std;

typedef long double ld;
typedef long long ll;

#define _ inline
#define f first
#define sec second
#define pb push_back
#define ins insert
#define ers erase
#define mk make_pair
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
//#define int ll

#define right rightt
#define left leftt
#define prev prevv
#define next nextt

mt19937 Random(time(0));

const int INF = 1e9 + 10;
const int MOD = 1e9 + 7;
const int P = 239017;
const long long BINF = 1e18 + 10;

const int B = 2010;

struct SQRT_Decomposition {
  vector<int> T, arr;
  int L[B], L2[B], R[B], R2[B];
  map<int, int> cnt[B];
  int n, cnt_blocks, len;
  SQRT_Decomposition(vector<int> _arr, int _n) {
    arr = _arr;
    n = _n;
    build();
  }
  void out() {
    for (auto it : T) {
      for (int i = L[it]; i <= R[it]; i++) {
        writeInt(arr[i], ' ');
      }
    }
    writeChar('\n');
  }
  void build() {
    cnt_blocks = (int)sqrt(n);
    len = n / cnt_blocks;
    if (cnt_blocks * len < n) {
      len++;
    }
    T.rsz(cnt_blocks);
    for (int i = 0; i < cnt_blocks; i++) {
      L[i] = len * i;
      R[i] = min(len * (i + 1), n) - 1;
      L2[i] = L[i], R2[i] = R[i];
      T[i] = i;
      for (int j = L[i]; j <= R[i]; j++) {
        cnt[i][arr[j]]++;
      }
    }
  }
  void rebuild() {
    vector<int> arr2;
    for (auto it : T) {
      for (int i = L[it]; i <= R[it]; i++) {
        arr2.pb(arr[i]);
      }
    }
    arr = arr2;
    for (int i = 0; i < cnt_blocks; i++) {
      cnt[i].clear();
    }
    build();
  }
  void create_new_block(int l, int r, int l2, int r2) {
    L[cnt_blocks] = l;
    R[cnt_blocks] = r;
    L2[cnt_blocks] = l2;
    R2[cnt_blocks] = r2;
    for (int i = l; i <= r; i++) {
      cnt[cnt_blocks][arr[i]]++;
    }
    cnt_blocks++;
  }
  void split(int x) {
    int ind = -1, pos = 0;
    for (auto it : T) {
      if (L2[it] <= x && R2[it] >= x) {
        ind = it;
        break;
      }
      pos++;
    }
    if (ind == -1 || R2[ind] == x) {
      return;
    }
    int ln = x - L2[ind];
    create_new_block(L[ind], L[ind] + ln, L2[ind], x);
    create_new_block(L[ind] + ln + 1, R[ind], x + 1, R2[ind]);
    vector<int> T2;
    for (int i = 0; i < pos; i++) {
      T2.pb(T[i]);
    }
    T2.pb(cnt_blocks - 2);
    T2.pb(cnt_blocks - 1);
    for (int i = pos + 1; i < (int)T.size(); i++) {
      T2.pb(T[i]);
    }
    T = T2;
  }
  void cut(int l, int r) {
    split(l - 1);
    split(r - 1);
    split(r);
    int pos1, pos2;
    for (int i = 0; i < (int)T.size(); i++) {
      if (L2[T[i]] == l) {
        pos1 = i;
      }
      if (R2[T[i]] == r) {
        pos2 = i;
      }
    }
    vector<int> T2;
    for (int i = 0; i < pos1; i++) {
      T2.pb(T[i]);
    }
    T2.pb(T[pos2]);
    for (int i = pos1; i < pos2; i++) {
      T2.pb(T[i]);
    }
    for (int i = pos2 + 1; i < (int)T.size(); i++) {
      T2.pb(T[i]);
    }
    T = T2;
    int cur = 0;
    for (auto it : T) {
      L2[it] = cur;
      R2[it] = cur + R[it] - L[it];
      cur = R2[it] + 1;
    }
  }
  int get(int l, int r, int k) {
    split(l - 1);
    split(r);
    int res = 0;
    for (auto it : T) {
      if (L2[it] >= l && R2[it] <= r) {
        res += cnt[it][k];
      }
    }
    return res;
  }
};

void source() {
  int n = readInt();
  vector<int> arr(n);
  for (auto &it : arr) {
    it = readInt();
  }
  SQRT_Decomposition A(arr, n);
  int m = readInt(), sz = (int)sqrt(n);
  int ans = 0;
  for (int i = 1; i <= m; i++) {
    if (A.cnt_blocks >= 4 * sz) {
      A.rebuild();
    }
    int type = readInt();
    if (type == 1) {
      int cur_l = readInt(), cur_r = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n;
      if (l > r) {
        swap(l, r);
      }
      A.cut(l, r);
    }
    else {
      int cur_l = readInt(), cur_r = readInt(), cur_k = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n, k = (cur_k + ans - 1) % n + 1;
      if (l > r) {
        swap(l, r);
      }
      ans = A.get(l, r, k);
      writeInt(ans, '\n');
    }
    //A.out();
  }
}

signed main() {
#ifdef EXTRATERRESTRIAL_
  assert(freopen("input.txt", "r", stdin));
  //assert(freopen("output.txt", "w", stdout));
#else
  //freopen(TASK".in", "r", stdin);
  //freopen(TASK".out", "w", stdout);
#endif
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  source();
  return 0;
}


//I_l_M_P
#include <bits/stdc++.h>

//#define FAST_ALLOCATOR_MEMORY 2.5e8

#ifdef FAST_ALLOCATOR_MEMORY
int allocator_pos = 0;
char allocator_memory[(int)FAST_ALLOCATOR_MEMORY];
inline void * operator new ( size_t n ) {
  char *res = allocator_memory + allocator_pos;
  allocator_pos += n;
  assert(allocator_pos <= (int)FAST_ALLOCATOR_MEMORY);
  return (void *)res;
}
inline void operator delete ( void * ) noexcept { }
//inline void * operator new [] ( size_t ) { assert(0); }
//inline void operator delete [] ( void * ) { assert(0); }
#endif

template <class T = int> inline T readInt();
inline double readDouble();
inline int readUInt();
inline int readChar();
inline void readWord(char *s);
inline bool readLine(char *s);
inline bool isEof();
inline int getChar();
inline int peekChar();
inline bool seekEof();
inline void skipBlanks();

template <class T> inline void writeInt(T x, char end = 0, int len = -1);
inline void writeChar(int x);
inline void writeWord(const char *s);
inline void writeDouble(double x, int len = 0);
inline void flush();

static struct buffer_flusher_t {
  ~buffer_flusher_t() {
    flush();
  }
} buffer_flusher;

static const int buf_size = 4096;

static unsigned char buf[buf_size];
static int buf_len = 0, buf_pos = 0;

inline bool isEof() {
  if (buf_pos == buf_len) {
    buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
    if (buf_pos == buf_len)
      return 1;
  }
  return 0;
}

inline int getChar() {
  return isEof() ? -1 : buf[buf_pos++];
}

inline int peekChar() {
  return isEof() ? -1 : buf[buf_pos];
}

inline bool seekEof() {
  int c;
  while ((c = peekChar()) != -1 && c <= 32)
    buf_pos++;
  return c == -1;
}

inline void skipBlanks() {
  while (!isEof() && buf[buf_pos] <= 32U)
    buf_pos++;
}

inline int readChar() {
  int c = getChar();
  while (c != -1 && c <= 32)
    c = getChar();
  return c;
}

inline int readUInt() {
  int c = readChar(), x = 0;
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return x;
}

template <class T>
inline T readInt() {
  int s = 1, c = readChar();
  T x = 0;
  if (c == '-')
    s = -1, c = getChar();
  else if (c == '+')
    c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return s == 1 ? x : -x;
}

inline double readDouble() {
  int s = 1, c = readChar();
  double x = 0;
  if (c == '-')
    s = -1, c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  if (c == '.') {
    c = getChar();
    double coef = 1;
    while ('0' <= c && c <= '9')
      x += (c - '0') * (coef *= 1e-1), c = getChar();
  }
  return s == 1 ? x : -x;
}

inline void readWord(char *s) {
  int c = readChar();
  while (c > 32)
    *s++ = c, c = getChar();
  *s = 0;
}

inline bool readLine(char *s) {
  int c = getChar();
  while (c != '\n' && c != -1)
    *s++ = c, c = getChar();
  *s = 0;
  return c != -1;
}

static int write_buf_pos = 0;
static char write_buf[buf_size];

inline void writeChar( int x ) {
  if (write_buf_pos == buf_size)
    fwrite(write_buf, 1, buf_size, stdout), write_buf_pos = 0;
  write_buf[write_buf_pos++] = x;
}

inline void flush() {
  if (write_buf_pos) {
    fwrite(write_buf, 1, write_buf_pos, stdout), write_buf_pos = 0;
    fflush(stdout);
  }
}

template <class T>
inline void writeInt(T x, char end, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  char s[24];
  int n = 0;
  while (x || !n)
    s[n++] = '0' + x % 10, x /= 10;
  while (n < output_len)
    s[n++] = '0';
  while (n--)
    writeChar(s[n]);
  if (end)
    writeChar(end);
}

inline void writeWord(const char *s) {
  while (*s)
    writeChar(*s++);
}

inline void writeDouble(double x, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  int t = (int)x;
  writeInt(t), x -= t;
  writeChar('.');
  for (int i = output_len - 1; i > 0; i--) {
    x *= 10;
    t = std::min(9, (int)x);
    writeChar('0' + t), x -= t;
  }
  x *= 10;
  t = std::min(9, (int)(x + 0.5));
  writeChar('0' + t);
}

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")

using namespace std;

typedef long double ld;
typedef long long ll;

#define _ inline
#define f first
#define sec second
#define pb push_back
#define ins insert
#define ers erase
#define mk make_pair
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
//#define int ll

#define right rightt
#define left leftt
#define prev prevv
#define next nextt

mt19937 Random(time(0));

const int INF = 1e9 + 10;
const int MOD = 1e9 + 7;
const int P = 239017;
const long long BINF = 1e18 + 10;

const int N = 1e5 + 10;
const int B = 2010;

struct SQRT_Decomposition {
  vector<int> T, arr, cnt[N];
  int L[B], L2[B], R[B], R2[B], used[N];
  int n, cnt_blocks, len, timer;
  SQRT_Decomposition(vector<int> _arr, int _n) {
    arr = _arr;
    n = _n;
    build();
  }
  _ void out() {
    for (auto it : T) {
      cout << L[it] << ' ' << R[it] << ' ' << L2[it] << ' ' << R2[it] << endl;
    }
    cout << endl;
  }
  _ void build() {
    timer++;
    cnt_blocks = (int)sqrt(n);
    len = n / cnt_blocks;
    if (cnt_blocks * len < n) {
      len++;
    }
    for (int i = 0; i < n; i++) {
      if (used[arr[i]] < timer) {
        used[arr[i]] = timer;
        cnt[arr[i]].clear();
      }
      cnt[arr[i]].pb(i);
    }
    T.rsz(cnt_blocks);
    for (int i = 0; i < cnt_blocks; i++) {
      L[i] = len * i;
      R[i] = min(len * (i + 1), n) - 1;
      L2[i] = L[i], R2[i] = R[i];
      T[i] = i;
    }
  }
  _ void rebuild() {
    vector<int> arr2;
    for (auto it : T) {
      for (int i = L[it]; i <= R[it]; i++) {
        arr2.pb(arr[i]);
      }
    }
    arr = arr2;
    build();
  }
  _ void create_new_block(int l, int r, int l2, int r2) {
    L[cnt_blocks] = l;
    R[cnt_blocks] = r;
    L2[cnt_blocks] = l2;
    R2[cnt_blocks] = r2;
    cnt_blocks++;
  }
  _ void split(int x) {
    int ind = -1, pos = 0;
    for (auto it : T) {
      if (L2[it] <= x && R2[it] >= x) {
        ind = it;
        break;
      }
      pos++;
    }
    if (ind == -1 || R2[ind] == x) {
      return;
    }
    int ln = x - L2[ind];
    create_new_block(L[ind], L[ind] + ln, L2[ind], x);
    create_new_block(L[ind] + ln + 1, R[ind], x + 1, R2[ind]);
    vector<int> T2;
    for (int i = 0; i < pos; i++) {
      T2.pb(T[i]);
    }
    T2.pb(cnt_blocks - 2);
    T2.pb(cnt_blocks - 1);
    for (int i = pos + 1; i < (int)T.size(); i++) {
      T2.pb(T[i]);
    }
    T = T2;
  }
  _ void cut(int l, int r) {
    split(l - 1);
    split(r - 1);
    split(r);
    int pos1, pos2;
    for (int i = 0; i < (int)T.size(); i++) {
      if (L2[T[i]] == l) {
        pos1 = i;
      }
      if (R2[T[i]] == r) {
        pos2 = i;
      }
    }
    vector<int> T2;
    for (int i = 0; i < pos1; i++) {
      T2.pb(T[i]);
    }
    T2.pb(T[pos2]);
    for (int i = pos1; i < pos2; i++) {
      T2.pb(T[i]);
    }
    for (int i = pos2 + 1; i < (int)T.size(); i++) {
      T2.pb(T[i]);
    }
    T = T2;
    int cur = 0;
    for (auto it : T) {
      L2[it] = cur;
      R2[it] = cur + R[it] - L[it];
      cur = R2[it] + 1;
    }
  }
  _ int get(int l, int r, int k) {
    split(l - 1);
    split(r);
    int res = 0;
    for (auto it : T) {
      if (L2[it] >= l && R2[it] <= r) {
        res += int(upper_bound(all(cnt[k]), R[it]) - lower_bound(all(cnt[k]), L[it]));
      }
    }
    return res;
  }
};

void source() {
  int n = readInt();
  vector<int> arr(n);
  for (auto &it : arr) {
    it = readInt();
  }
  SQRT_Decomposition A(arr, n);
  int m = readInt(), sz = (int)sqrt(n);
  int ans = 0;
  for (int i = 1; i <= m; i++) {
    if (i % sz == 0) {
      A.rebuild();
    }
    int type = readInt();
    if (type == 1) {
      int cur_l = readInt(), cur_r = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n;
      if (l > r) {
        swap(l, r);
      }
      A.cut(l, r);
    }
    else {
      int cur_l = readInt(), cur_r = readInt(), cur_k = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n, k = (cur_k + ans - 1) % n + 1;
      if (l > r) {
        swap(l, r);
      }
      ans = A.get(l, r, k);
      writeInt(ans, '\n');
    }
  }
}

signed main() {
#ifdef EXTRATERRESTRIAL_
  assert(freopen("input.txt", "r", stdin));
  //assert(freopen("output.txt", "w", stdout));
#else
  //freopen(TASK".in", "r", stdin);
  //freopen(TASK".out", "w", stdout);
#endif
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  source();
  return 0;
}


  //I_l_M_P
  #include <bits/stdc++.h>

  #ifdef FAST_ALLOCATOR_MEMORY
  int allocator_pos = 0;
  char allocator_memory[(int)FAST_ALLOCATOR_MEMORY];
  inline void * operator new ( size_t n ) {
    char *res = allocator_memory + allocator_pos;
    allocator_pos += n;
    assert(allocator_pos <= (int)FAST_ALLOCATOR_MEMORY);
    return (void *)res;
  }
  inline void operator delete ( void * ) noexcept { }
  //inline void * operator new [] ( size_t ) { assert(0); }
  //inline void operator delete [] ( void * ) { assert(0); }
  #endif

  template <class T = int> inline T readInt();
  inline double readDouble();
  inline int readUInt();
  inline int readChar();
  inline void readWord(char *s);
  inline bool readLine(char *s);
  inline bool isEof();
  inline int getChar();
  inline int peekChar();
  inline bool seekEof();
  inline void skipBlanks();

  template <class T> inline void writeInt(T x, char end = 0, int len = -1);
  inline void writeChar(int x);
  inline void writeWord(const char *s);
  inline void writeDouble(double x, int len = 0);
  inline void flush();

  static struct buffer_flusher_t {
    ~buffer_flusher_t() {
      flush();
    }
  } buffer_flusher;

  static const int buf_size = 4096;

  static unsigned char buf[buf_size];
  static int buf_len = 0, buf_pos = 0;

  inline bool isEof() {
    if (buf_pos == buf_len) {
      buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
      if (buf_pos == buf_len)
        return 1;
    }
    return 0;
  }

  inline int getChar() {
    return isEof() ? -1 : buf[buf_pos++];
  }

  inline int peekChar() {
    return isEof() ? -1 : buf[buf_pos];
  }

  inline bool seekEof() {
    int c;
    while ((c = peekChar()) != -1 && c <= 32)
      buf_pos++;
    return c == -1;
  }

  inline void skipBlanks() {
    while (!isEof() && buf[buf_pos] <= 32U)
      buf_pos++;
  }

  inline int readChar() {
    int c = getChar();
    while (c != -1 && c <= 32)
      c = getChar();
    return c;
  }

  inline int readUInt() {
    int c = readChar(), x = 0;
    while ('0' <= c && c <= '9')
      x = x * 10 + c - '0', c = getChar();
    return x;
  }

  template <class T>
  inline T readInt() {
    int s = 1, c = readChar();
    T x = 0;
    if (c == '-')
      s = -1, c = getChar();
    else if (c == '+')
      c = getChar();
    while ('0' <= c && c <= '9')
      x = x * 10 + c - '0', c = getChar();
    return s == 1 ? x : -x;
  }

  inline double readDouble() {
    int s = 1, c = readChar();
    double x = 0;
    if (c == '-')
      s = -1, c = getChar();
    while ('0' <= c && c <= '9')
      x = x * 10 + c - '0', c = getChar();
    if (c == '.') {
      c = getChar();
      double coef = 1;
      while ('0' <= c && c <= '9')
        x += (c - '0') * (coef *= 1e-1), c = getChar();
    }
    return s == 1 ? x : -x;
  }

  inline void readWord(char *s) {
    int c = readChar();
    while (c > 32)
      *s++ = c, c = getChar();
    *s = 0;
  }

  inline bool readLine(char *s) {
    int c = getChar();
    while (c != '\n' && c != -1)
      *s++ = c, c = getChar();
    *s = 0;
    return c != -1;
  }

  static int write_buf_pos = 0;
  static char write_buf[buf_size];

  inline void writeChar( int x ) {
    if (write_buf_pos == buf_size)
      fwrite(write_buf, 1, buf_size, stdout), write_buf_pos = 0;
    write_buf[write_buf_pos++] = x;
  }

  inline void flush() {
    if (write_buf_pos) {
      fwrite(write_buf, 1, write_buf_pos, stdout), write_buf_pos = 0;
      fflush(stdout);
    }
  }

  template <class T>
  inline void writeInt(T x, char end, int output_len) {
    if (x < 0)
      writeChar('-'), x = -x;
    char s[24];
    int n = 0;
    while (x || !n)
      s[n++] = '0' + x % 10, x /= 10;
    while (n < output_len)
      s[n++] = '0';
    while (n--)
      writeChar(s[n]);
    if (end)
      writeChar(end);
  }

  inline void writeWord(const char *s) {
    while (*s)
      writeChar(*s++);
  }

  inline void writeDouble(double x, int output_len) {
    if (x < 0)
      writeChar('-'), x = -x;
    int t = (int)x;
    writeInt(t), x -= t;
    writeChar('.');
    for (int i = output_len - 1; i > 0; i--) {
      x *= 10;
      t = std::min(9, (int)x);
      writeChar('0' + t), x -= t;
    }
    x *= 10;
    t = std::min(9, (int)(x + 0.5));
    writeChar('0' + t);
  }

  #pragma GCC optimize("O3,unroll-loops")
  #pragma GCC target("sse,sse2,sse3,ssse3,sse4")

  using namespace std;

  typedef long double ld;
  typedef long long ll;

  #define _ inline
  #define f first
  #define sec second
  #define pb push_back
  #define ins insert
  #define ers erase
  #define mk make_pair
  #define all(x) (x).begin(), (x).end()
  #define rall(x) (x).rbegin(), (x).rend()
  #define rsz resize
  //#define int ll

  #define right rightt
  #define left leftt
  #define prev prevv
  #define next nextt

  mt19937 Random(time(0));

  const int INF = 1e9 + 10;
  const int MOD = 1e9 + 7;
  const int P = 239017;
  const long long BINF = 1e18 + 10;

  const int N = 1e5 + 10;
  const int B = 610;

  struct SQRT_Decomposition {
    vector<int> T, arr;
    int cnt[B][N], L[B], L2[B], R[B], R2[B], n, cnt_blocks, len;
    SQRT_Decomposition(vector<int> _arr, int _n) {
      arr = _arr;
      n = _n;
      build();
    }
    void out() {
      for (auto it : T) {
        for (int i = L[it]; i <= R[it]; i++) {
          writeInt(arr[i], ' ');
        }
      }
      writeChar('\n');
    }
    _ void build() {
      cnt_blocks = min(150, (int)sqrt(n));
      len = n / cnt_blocks;
      if (cnt_blocks * len < n) {
        len++;
      }
      T.rsz(cnt_blocks);
      for (int i = 0; i < cnt_blocks; i++) {
        L[i] = len * i;
        R[i] = min(len * (i + 1), n) - 1;
        L2[i] = L[i], R2[i] = R[i];
        T[i] = i;
        for (int j = L[i]; j <= R[i]; j++) {
          cnt[i][arr[j]]++;
        }
      }
    }
    _ void rebuild() {
      vector<int> arr2;
      for (auto it : T) {
        for (int i = L[it]; i <= R[it]; i++) {
          arr2.pb(arr[i]);
        }
      }
      arr = arr2;
      for (int i = 0; i < cnt_blocks; i++) {
        for (int j = L[i]; j <= R[i]; j++) {
          cnt[i][arr[j]] = 0;
        }
      }
      build();
    }
    _ void create_new_block(int l, int r, int l2, int r2) {
      L[cnt_blocks] = l;
      R[cnt_blocks] = r;
      L2[cnt_blocks] = l2;
      R2[cnt_blocks] = r2;
      for (int i = l; i <= r; i++) {
        cnt[cnt_blocks][arr[i]]++;
      }
      cnt_blocks++;
    }
    _ void split(int x) {
      int ind = -1, pos = 0;
      for (auto it : T) {
        if (L2[it] <= x && R2[it] >= x) {
          ind = it;
          break;
        }
        pos++;
      }
      if (ind == -1 || R2[ind] == x) {
        return;
      }
      int ln = x - L2[ind];
      create_new_block(L[ind], L[ind] + ln, L2[ind], x);
      create_new_block(L[ind] + ln + 1, R[ind], x + 1, R2[ind]);
      vector<int> T2;
      for (int i = 0; i < pos; i++) {
        T2.pb(T[i]);
      }
      T2.pb(cnt_blocks - 2);
      T2.pb(cnt_blocks - 1);
      for (int i = pos + 1; i < (int)T.size(); i++) {
        T2.pb(T[i]);
      }
      T = T2;
    }
    _ void cut(int l, int r) {
      split(l - 1);
      split(r - 1);
      split(r);
      int pos1, pos2;
      for (int i = 0; i < (int)T.size(); i++) {
        if (L2[T[i]] == l) {
          pos1 = i;
        }
        if (R2[T[i]] == r) {
          pos2 = i;
        }
      }
      vector<int> T2;
      for (int i = 0; i < pos1; i++) {
        T2.pb(T[i]);
      }
      T2.pb(T[pos2]);
      for (int i = pos1; i < pos2; i++) {
        T2.pb(T[i]);
      }
      for (int i = pos2 + 1; i < (int)T.size(); i++) {
        T2.pb(T[i]);
      }
      T = T2;
      int cur = 0;
      for (auto it : T) {
        L2[it] = cur;
        R2[it] = cur + R[it] - L[it];
        cur = R2[it] + 1;
      }
    }
    _ int get(int l, int r, int k) {
      split(l - 1);
      split(r);
      int res = 0;
      for (auto it : T) {
        if (L2[it] >= l && R2[it] <= r) {
          res += cnt[it][k];
        }
      }
      return res;
    }
  };
  void source() {
    int n = readInt();
    vector<int> arr(n);
    for (auto &it : arr) {
      it = readInt();
    }
    SQRT_Decomposition A(arr, n);
    int m = readInt();
    int ans = 0;
    for (int i = 1; i <= m; i++) {
      if (A.cnt_blocks >= 600) {
        A.rebuild();
      }
      int type = readInt();
      if (type == 1) {
        int cur_l = readInt(), cur_r = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n;
        if (l > r) {
          swap(l, r);
        }
        A.cut(l, r);
      }
      else {
        int cur_l = readInt(), cur_r = readInt(), cur_k = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n, k = (cur_k + ans - 1) % n + 1;
        if (l > r) {
          swap(l, r);
        }
        ans = A.get(l, r, k);
        writeInt(ans, '\n');
      }
    }
  }

  signed main() {
  #ifdef EXTRATERRESTRIAL_
    assert(freopen("input.txt", "r", stdin));
    //assert(freopen("output.txt", "w", stdout));
  #else
    //assert(freopen(TASK".in", "r", stdin));
    //assert(freopen(TASK".out", "w", stdout));
  #endif
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    source();
  #ifdef EXTRATERRESTRIAL_
    writeWord("\n\t");
    writeDouble((double)clock() / (double)CLOCKS_PER_SEC, 10);
    writeWord(" seconds\n\n");
  #endif
    return 0;
  }


#include <bits/stdc++.h>

#ifdef FAST_ALLOCATOR_MEMORY
int allocator_pos = 0;
char allocator_memory[(int)FAST_ALLOCATOR_MEMORY];
inline void * operator new ( size_t n ) {
  char *res = allocator_memory + allocator_pos;
  allocator_pos += n;
  assert(allocator_pos <= (int)FAST_ALLOCATOR_MEMORY);
  return (void *)res;
}
inline void operator delete ( void * ) noexcept { }
//inline void * operator new [] ( size_t ) { assert(0); }
//inline void operator delete [] ( void * ) { assert(0); }
#endif

template <class T = int> inline T readInt();
inline double readDouble();
inline int readUInt();
inline int readChar();
inline void readWord(char *s);
inline bool readLine(char *s);
inline bool isEof();
inline int getChar();
inline int peekChar();
inline bool seekEof();
inline void skipBlanks();

template <class T> inline void writeInt(T x, char end = 0, int len = -1);
inline void writeChar(int x);
inline void writeWord(const char *s);
inline void writeDouble(double x, int len = 0);
inline void flush();

static struct buffer_flusher_t {
  ~buffer_flusher_t() {
    flush();
  }
} buffer_flusher;

static const int buf_size = 4096;

static unsigned char buf[buf_size];
static int buf_len = 0, buf_pos = 0;

inline bool isEof() {
  if (buf_pos == buf_len) {
    buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
    if (buf_pos == buf_len)
      return 1;
  }
  return 0;
}

inline int getChar() {
  return isEof() ? -1 : buf[buf_pos++];
}

inline int peekChar() {
  return isEof() ? -1 : buf[buf_pos];
}

inline bool seekEof() {
  int c;
  while ((c = peekChar()) != -1 && c <= 32)
    buf_pos++;
  return c == -1;
}

inline void skipBlanks() {
  while (!isEof() && buf[buf_pos] <= 32U)
    buf_pos++;
}

inline int readChar() {
  int c = getChar();
  while (c != -1 && c <= 32)
    c = getChar();
  return c;
}

inline int readUInt() {
  int c = readChar(), x = 0;
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return x;
}

template <class T>
inline T readInt() {
  int s = 1, c = readChar();
  T x = 0;
  if (c == '-')
    s = -1, c = getChar();
  else if (c == '+')
    c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return s == 1 ? x : -x;
}

inline double readDouble() {
  int s = 1, c = readChar();
  double x = 0;
  if (c == '-')
    s = -1, c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  if (c == '.') {
    c = getChar();
    double coef = 1;
    while ('0' <= c && c <= '9')
      x += (c - '0') * (coef *= 1e-1), c = getChar();
  }
  return s == 1 ? x : -x;
}

inline void readWord(char *s) {
  int c = readChar();
  while (c > 32)
    *s++ = c, c = getChar();
  *s = 0;
}

inline bool readLine(char *s) {
  int c = getChar();
  while (c != '\n' && c != -1)
    *s++ = c, c = getChar();
  *s = 0;
  return c != -1;
}

static int write_buf_pos = 0;
static char write_buf[buf_size];

inline void writeChar( int x ) {
  if (write_buf_pos == buf_size)
    fwrite(write_buf, 1, buf_size, stdout), write_buf_pos = 0;
  write_buf[write_buf_pos++] = x;
}

inline void flush() {
  if (write_buf_pos) {
    fwrite(write_buf, 1, write_buf_pos, stdout), write_buf_pos = 0;
    fflush(stdout);
  }
}

template <class T>
inline void writeInt(T x, char end, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  char s[24];
  int n = 0;
  while (x || !n)
    s[n++] = '0' + x % 10, x /= 10;
  while (n < output_len)
    s[n++] = '0';
  while (n--)
    writeChar(s[n]);
  if (end)
    writeChar(end);
}

inline void writeWord(const char *s) {
  while (*s)
    writeChar(*s++);
}

inline void writeDouble(double x, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  int t = (int)x;
  writeInt(t), x -= t;
  writeChar('.');
  for (int i = output_len - 1; i > 0; i--) {
    x *= 10;
    t = std::min(9, (int)x);
    writeChar('0' + t), x -= t;
  }
  x *= 10;
  t = std::min(9, (int)(x + 0.5));
  writeChar('0' + t);
}

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")

using namespace std;

typedef long double ld;
typedef long long ll;

#define _ inline
#define f first
#define sec second
#define pb push_back
#define ins insert
#define ers erase
#define mk make_pair
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
//#define int ll

#define right rightt
#define left leftt
#define prev prevv
#define next nextt

mt19937 Random(time(0));

const int INF = 1e9 + 10;
const int MOD = 1e9 + 7;
const int P = 239017;
const long long BINF = 1e18 + 10;

const int R = 400;
const int N = 1e5 + 10;
const int SZ = (int)sqrt(N);
int a[N], n, cur[SZ + 10][3 * SZ + 10], sz[SZ + 10], cnt_blocks;
short calc[SZ + 10][N];

inline void build() {
  cnt_blocks = 0;
  for (int i = 0; i < n; i += SZ) {
    int to = min(i + SZ, n) - 1;
    for (int j = i; j <= to; j++) {
      calc[cnt_blocks][a[j]]++;
      cur[cnt_blocks][sz[cnt_blocks]++] = a[j];
    }
    cnt_blocks++;
  }
}

inline void rebuild() {
  int ind = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    for (int j = 0; j < sz[i]; j++) {
      a[ind++] = cur[i][j];
      calc[i][cur[i][j]] = 0;
    }
    sz[i] = 0;
  }
  build();
}

inline int erase(int ind) {
  int sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > ind) {
      int ps = ind - sum, res = cur[i][ps];
      calc[i][res]--;
      for (int j = ps; j + 1 < sz[i]; j++) {
        cur[i][j] = cur[i][j + 1];
      }
      sz[i]--;
      return res;
    }
    sum += sz[i];
  }
  return 0;
}

inline void insert(int ind, int vl) {
  int sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > ind) {
      int ps = ind - sum + 1;
      calc[i][vl]++;
      sz[i]++;
      for (int j = sz[i] - 1; j > ps; j--) {
        cur[i][j] = cur[i][j - 1];
      }
      cur[i][ps] = vl;
      return;
    }
    sum += sz[i];
  }
  return;
}

inline void shift(int l, int r) {
  insert(l - 1, erase(r));
}

inline int get(int r, int vl) {
  int res = 0, sum = 0;
  for (int i = 0; i < cnt_blocks; i++) {
    if (sum + sz[i] > r) {
      int ps = r - sum;
      for (int j = 0; j <= ps; j++) {
        res += (cur[i][j] == vl);
      }
      break;
    }
    res += calc[i][vl];
    sum += sz[i];
  }
  return res;
}

void source() {
  n = readInt();
  for (int i = 0; i < n; i++) {
    a[i] = readInt();
  }
  int m = readInt();
  int ans = 0;
  for (int i = 0; i < m; i++) {
    if (i % R == 0) {
      rebuild();
    }
    int type = readInt();
    if (type == 1) {
      int cur_l = readInt(), cur_r = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n;
      if (l > r) {
        swap(l, r);
      }
      shift(l, r);
    }
    else {
      int cur_l = readInt(), cur_r = readInt(), cur_k = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n, k = (cur_k + ans - 1) % n + 1;
      if (l > r) {
        swap(l, r);
      }
      ans = get(r, k) - get(l - 1, k);
      writeInt(ans, '\n');
    }
  }
}

signed main() {
#ifdef extraterrestrial_
  assert(freopen("input.txt", "r", stdin));
  //assert(freopen("output.txt", "w", stdout));
#else
  //freopen(TASK".in", "r", stdin);
  //freopen(TASK".out", "w", stdout);
#endif
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  source();
  return 0;
}


//I_l_M_P
#include <bits/stdc++.h>

#ifdef FAST_ALLOCATOR_MEMORY
int allocator_pos = 0;
char allocator_memory[(int)FAST_ALLOCATOR_MEMORY];
inline void * operator new ( size_t n ) {
  char *res = allocator_memory + allocator_pos;
  allocator_pos += n;
  assert(allocator_pos <= (int)FAST_ALLOCATOR_MEMORY);
  return (void *)res;
}
inline void operator delete ( void * ) noexcept { }
//inline void * operator new [] ( size_t ) { assert(0); }
//inline void operator delete [] ( void * ) { assert(0); }
#endif

template <class T = int> inline T readInt();
inline double readDouble();
inline int readUInt();
inline int readChar();
inline void readWord(char *s);
inline bool readLine(char *s);
inline bool isEof();
inline int getChar();
inline int peekChar();
inline bool seekEof();
inline void skipBlanks();

template <class T> inline void writeInt(T x, char end = 0, int len = -1);
inline void writeChar(int x);
inline void writeWord(const char *s);
inline void writeDouble(double x, int len = 0);
inline void flush();

static struct buffer_flusher_t {
  ~buffer_flusher_t() {
    flush();
  }
} buffer_flusher;

static const int buf_size = 4096;

static unsigned char buf[buf_size];
static int buf_len = 0, buf_pos = 0;

inline bool isEof() {
  if (buf_pos == buf_len) {
    buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
    if (buf_pos == buf_len)
      return 1;
  }
  return 0;
}

inline int getChar() {
  return isEof() ? -1 : buf[buf_pos++];
}

inline int peekChar() {
  return isEof() ? -1 : buf[buf_pos];
}

inline bool seekEof() {
  int c;
  while ((c = peekChar()) != -1 && c <= 32)
    buf_pos++;
  return c == -1;
}

inline void skipBlanks() {
  while (!isEof() && buf[buf_pos] <= 32U)
    buf_pos++;
}

inline int readChar() {
  int c = getChar();
  while (c != -1 && c <= 32)
    c = getChar();
  return c;
}

inline int readUInt() {
  int c = readChar(), x = 0;
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return x;
}

template <class T>
inline T readInt() {
  int s = 1, c = readChar();
  T x = 0;
  if (c == '-')
    s = -1, c = getChar();
  else if (c == '+')
    c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  return s == 1 ? x : -x;
}

inline double readDouble() {
  int s = 1, c = readChar();
  double x = 0;
  if (c == '-')
    s = -1, c = getChar();
  while ('0' <= c && c <= '9')
    x = x * 10 + c - '0', c = getChar();
  if (c == '.') {
    c = getChar();
    double coef = 1;
    while ('0' <= c && c <= '9')
      x += (c - '0') * (coef *= 1e-1), c = getChar();
  }
  return s == 1 ? x : -x;
}

inline void readWord(char *s) {
  int c = readChar();
  while (c > 32)
    *s++ = c, c = getChar();
  *s = 0;
}

inline bool readLine(char *s) {
  int c = getChar();
  while (c != '\n' && c != -1)
    *s++ = c, c = getChar();
  *s = 0;
  return c != -1;
}

static int write_buf_pos = 0;
static char write_buf[buf_size];

inline void writeChar( int x ) {
  if (write_buf_pos == buf_size)
    fwrite(write_buf, 1, buf_size, stdout), write_buf_pos = 0;
  write_buf[write_buf_pos++] = x;
}

inline void flush() {
  if (write_buf_pos) {
    fwrite(write_buf, 1, write_buf_pos, stdout), write_buf_pos = 0;
    fflush(stdout);
  }
}

template <class T>
inline void writeInt(T x, char end, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  char s[24];
  int n = 0;
  while (x || !n)
    s[n++] = '0' + x % 10, x /= 10;
  while (n < output_len)
    s[n++] = '0';
  while (n--)
    writeChar(s[n]);
  if (end)
    writeChar(end);
}

inline void writeWord(const char *s) {
  while (*s)
    writeChar(*s++);
}

inline void writeDouble(double x, int output_len) {
  if (x < 0)
    writeChar('-'), x = -x;
  int t = (int)x;
  writeInt(t), x -= t;
  writeChar('.');
  for (int i = output_len - 1; i > 0; i--) {
    x *= 10;
    t = std::min(9, (int)x);
    writeChar('0' + t), x -= t;
  }
  x *= 10;
  t = std::min(9, (int)(x + 0.5));
  writeChar('0' + t);
}

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")

using namespace std;

typedef long double ld;
typedef long long ll;

#define _ inline
#define f first
#define sec second
#define pb push_back
#define ins insert
#define ers erase
#define mk make_pair
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
//#define int ll

#define right rightt
#define left leftt
#define prev prevv
#define next nextt

mt19937 Random(time(0));

const int INF = 1e9 + 10;
const int MOD = 1e9 + 7;
const int P = 239017;
const long long BINF = 1e18 + 10;

const int N = 1e5 + 10;
const int B = 570;

struct SQRT_Decomposition {
  vector<int> T, arr;
  int cnt[B][N], L[B], L2[B], R[B], R2[B], n, cnt_blocks, len;
  SQRT_Decomposition(vector<int> _arr, int _n) {
    arr = _arr;
    n = _n;
    build();
  }
  void out() {
    for (auto it : T) {
      for (int i = L[it]; i <= R[it]; i++) {
        writeInt(arr[i], ' ');
      }
    }
    writeChar('\n');
  }
  void build() {
    cnt_blocks = min(100, (int)sqrt(n));
    len = n / cnt_blocks;
    if (cnt_blocks * len < n) {
      len++;
    }
    T.rsz(cnt_blocks);
    for (int i = 0; i < cnt_blocks; i++) {
      L[i] = len * i;
      R[i] = min(len * (i + 1), n) - 1;
      L2[i] = L[i], R2[i] = R[i];
      T[i] = i;
      for (int j = L[i]; j <= R[i]; j++) {
        cnt[i][arr[j]]++;
      }
    }
  }
  void rebuild() {
    vector<int> arr2;
    for (auto it : T) {
      for (int i = L[it]; i <= R[it]; i++) {
        arr2.pb(arr[i]);
      }
    }
    arr = arr2;
    for (int i = 0; i < cnt_blocks; i++) {
      for (int j = L[i]; j <= R[i]; j++) {
        cnt[i][arr[j]] = 0;
      }
    }
    build();
  }
  void create_new_block(int l, int r, int l2, int r2) {
    L[cnt_blocks] = l;
    R[cnt_blocks] = r;
    L2[cnt_blocks] = l2;
    R2[cnt_blocks] = r2;
    for (int i = l; i <= r; i++) {
      cnt[cnt_blocks][arr[i]]++;
    }
    cnt_blocks++;
  }
  void split(int x) {
    int ind = -1, pos = 0;
    for (auto it : T) {
      if (L2[it] <= x && R2[it] >= x) {
        ind = it;
        break;
      }
      pos++;
    }
    if (ind == -1 || R2[ind] == x) {
      return;
    }
    int ln = x - L2[ind];
    create_new_block(L[ind], L[ind] + ln, L2[ind], x);
    create_new_block(L[ind] + ln + 1, R[ind], x + 1, R2[ind]);
    vector<int> T2;
    for (int i = 0; i < pos; i++) {
      T2.pb(T[i]);
    }
    T2.pb(cnt_blocks - 2);
    T2.pb(cnt_blocks - 1);
    for (int i = pos + 1; i < (int)T.size(); i++) {
      T2.pb(T[i]);
    }
    T = T2;
  }
  void cut(int l, int r) {
    split(l - 1);
    split(r - 1);
    split(r);
    int pos1, pos2;
    for (int i = 0; i < (int)T.size(); i++) {
      if (L2[T[i]] == l) {
        pos1 = i;
      }
      if (R2[T[i]] == r) {
        pos2 = i;
      }
    }
    vector<int> T2;
    for (int i = 0; i < pos1; i++) {
      T2.pb(T[i]);
    }
    T2.pb(T[pos2]);
    for (int i = pos1; i < pos2; i++) {
      T2.pb(T[i]);
    }
    for (int i = pos2 + 1; i < (int)T.size(); i++) {
      T2.pb(T[i]);
    }
    T = T2;
    int cur = 0;
    for (auto it : T) {
      L2[it] = cur;
      R2[it] = cur + R[it] - L[it];
      cur = R2[it] + 1;
    }
  }
  int get(int l, int r, int k) {
    split(l - 1);
    split(r);
    int res = 0;
    for (auto it : T) {
      if (L2[it] >= l && R2[it] <= r) {
        res += cnt[it][k];
      }
    }
    return res;
  }
};
void source() {
  int n = readInt();
  vector<int> arr(n);
  for (auto &it : arr) {
    it = readInt();
  }
  SQRT_Decomposition A(arr, n);
  int m = readInt();
  int ans = 0;
  for (int i = 1; i <= m; i++) {
    if (A.cnt_blocks >= 550) {
      A.rebuild();
    }
    int type = readInt();
    if (type == 1) {
      int cur_l = readInt(), cur_r = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n;
      if (l > r) {
        swap(l, r);
      }
      A.cut(l, r);
    }
    else {
      int cur_l = readInt(), cur_r = readInt(), cur_k = readInt(), l = (cur_l + ans - 1) % n, r = (cur_r + ans - 1) % n, k = (cur_k + ans - 1) % n + 1;
      if (l > r) {
        swap(l, r);
      }
      ans = A.get(l, r, k);
      writeInt(ans, '\n');
    }
  }
}

signed main() {
#ifdef EXTRATERRESTRIAL_
  assert(freopen("input.txt", "r", stdin));
  //assert(freopen("output.txt", "w", stdout));
#else
  //assert(freopen(TASK".in", "r", stdin));
  //assert(freopen(TASK".out", "w", stdout));
#endif
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  source();
#ifdef EXTRATERRESTRIAL_
  writeWord("\n\t");
  writeDouble((double)clock() / (double)CLOCKS_PER_SEC, 10);
  writeWord(" seconds\n\n");
#endif
  return 0;
}


n=int(input())
list=[]
appear={}
for i in range(n):
    list.append(input())
l=len(list)
for i in range(l):
    name=list[l-1-i]
    if appear.get(name,0)==0:
        print(name)
        appear[name]=1


from collections import OrderedDict as D
d=D()
for n in range(int(input())):
	x=input();d[x]=d.pop(x,None)
print('\n'.join(list(d.keys())[::-1]))


n = int(input())
l = []

for _ in range(n):
	l.append(input())

answer = []
s = set()

for i in range(n - 1, 0, -1):
	if l[i] not in s:
		s.add(l[i])
		answer.append(l[i])

for _ in answer:
  print(_)


n = map(int, input())
l = []

for _ in range(n):
	l.append(input())

answer = []
s = set()

for i in range(n - 1, 0, -1):
	if l[i] not in s:
		s.add(l[i])
		answer.append(l[i])

print(answer)