Problem: Serega loves fun. However, everyone has fun in the unique manner. Serega has fun by solving query problems. One day Fedor came up with such a problem.

You are given an array a consisting of n positive integers and queries to it. The queries can be of two types:

  1. Make a unit cyclic shift to the right on the segment from l to r (both borders inclusive). That is rearrange elements of the array in the following manner:a[l], a[l + 1], ..., a[r - 1], a[r] → a[r], a[l], a[l + 1], ..., a[r - 1].
  2. Count how many numbers equal to k are on the segment from l to r (both borders inclusive). 



Fedor hurried to see Serega enjoy the problem and Serega solved it really quickly. Let's see, can you solve it?

Input

The first line contains integer n (1 ≤ n ≤ 105) — the number of elements of the array. The second line contains n integers a[1], a[2], ..., a[n] (1 ≤ a[i] ≤ n).

The third line contains a single integer q (1 ≤ q ≤ 105) — the number of queries. The next q lines contain the queries.

As you need to respond to the queries online, the queries will be encoded. A query of the first type will be given in format: 1 l'i r'i. A query of the second type will be given in format: 2 l'i r'i k'i. All the number in input are integer. They satisfy the constraints: 1 ≤ l'i, r'i, k'i ≤ n.

To decode the queries from the data given in input, you need to perform the following transformations:

li = ((l'i + lastans - 1) mod n) + 1; ri = ((r'i + lastans - 1) mod n) + 1; ki = ((k'i + lastans - 1) mod n) + 1.

Where lastans is the last reply to the query of the 2-nd type (initially, lastans = 0). If after transformation li is greater than ri, you must swap these values.

Output

For each query of the 2-nd type print the answer on a single line.

Examples

Input

7
6 6 2 7 4 2 5
7
1 3 6
2 2 4 2
2 2 4 7
2 2 2 5
1 2 6
1 1 4
2 1 7 3


Output

2
1
0
0


Input

8
8 4 2 2 7 7 8 8
8
1 8 8
2 8 1 7
1 8 1
1 7 3
2 8 8 3
1 1 4
1 2 7
1 4 5


Output

2
0

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
template <typename Tp, int N>
struct holder {
  Tp da[N];
  int sz;
  void clear() { sz = 0; }
  holder() { clear(); }
  void push_back(const Tp &x) { da[sz++] = x; }
  const Tp &pop_back() { return da[--sz]; }
};
const int N = 200000 + 10;
namespace sgt {
const double alpha = 0.7;
struct Node {
  double L, R;
  double mid() const { return (L + R) / 2; }
  Node *ch[2];
  int key, sz, exist, nc;
  void maintain() {
    sz = ch[0]->sz + ch[1]->sz + exist;
    nc = ch[0]->nc + ch[1]->nc + 1;
  }
  bool bad() { return ch[0]->nc > nc * alpha || ch[1]->nc > nc * alpha; }
  double kth(int k) {
    if (ch[0]->sz >= k) return ch[0]->kth(k);
    int s = ch[0]->sz + exist;
    if (exist && s == k) return mid();
    return ch[1]->kth(k - s);
  }
} pool[N * 2], *null, *pis, *root;
holder<Node *, N> cache;
Node *newnode(double L, double R, int key) {
  Node *o = pis++;
  o->ch[0] = o->ch[1] = null;
  o->sz = o->nc = o->exist = 1;
  o->L = L, o->R = R;
  o->key = key;
  return o;
}
pair<Node **, Node *> insert(Node *&o, double L, double R, int k, int key) {
  if (o == null) return make_pair(&null, o = newnode(L, R, key));
  pair<Node **, Node *> res;
  double M = (L + R) / 2;
  if (o->ch[0]->sz >= k)
    res = insert(o->ch[0], L, M, k, key);
  else
    res = insert(o->ch[1], M, R, k - o->ch[0]->sz - o->exist, key);
  if (o->bad()) res.first = &o;
  return o->maintain(), res;
}
Node *remove(Node *&o, int k) {
  Node *res;
  if (o->ch[0]->sz >= k)
    res = remove(o->ch[0], k);
  else if (o->ch[0]->sz + o->exist == k)
    res = o, o->exist = 0;
  else
    res = remove(o->ch[1], k - o->ch[0]->sz - o->exist);
  return o->maintain(), res;
}
void divide(Node *&o, Node *da[], int l, int r, double L, double R) {
  if (l > r) return o = null, void();
  int mid = (l + r) >> 1;
  double M = (L + R) / 2;
  o = da[mid];
  o->L = L, o->R = R;
  divide(o->ch[0], da, l, mid - 1, L, M);
  divide(o->ch[1], da, mid + 1, r, M, R);
  o->maintain();
}
void print(Node *o) {
  if (o == null) return;
  print(o->ch[0]);
  if (o->exist) cache.push_back(o);
  print(o->ch[1]);
}
Node **cr;
Node *insert(int k, int key) {
  pair<Node **, Node *> res = insert(root, 0, 1, k, key);
  cr = res.first;
  return res.second;
}
void rebuild() {
  Node *&o = *cr;
  if (o != null) {
    cache.clear();
    print(o);
    divide(o, cache.da, 0, cache.sz - 1, o->L, o->R);
  }
}
void init() {
  pis = pool;
  null = newnode(0, 0, 0);
  null->ch[0] = null->ch[1] = null;
  null->sz = null->nc = 0;
}
void debug(Node *o) {
  if (o == null) return;
  debug(o->ch[0]);
  if (o->exist) printf("(%d, %.3f) ", o->key, o->mid());
  debug(o->ch[1]);
}
}  // namespace sgt
namespace treap {
struct Node {
  sgt::Node *r;
  Node *ch[2];
  int sz, fix;
  double key() const { return r->mid(); }
  void maintain();
} pool[N * 2], *pis, *null, *root[N];
void Node::maintain() {
  assert(this != null);
  sz = ch[0]->sz + ch[1]->sz + 1;
}
Node *newnode(sgt::Node *r) {
  Node *o = pis++;
  o->r = r;
  o->ch[0] = o->ch[1] = null;
  o->fix = rand();
  o->sz = 1;
  return o;
}
void rotate(Node *&o, int d) {
  Node *t = o->ch[d];
  o->ch[d] = t->ch[d ^ 1];
  t->ch[d ^ 1] = o;
  o->maintain();
  (o = t)->maintain();
}
void insert(Node *&o, sgt::Node *r) {
  if (o == null) return o = newnode(r), void();
  int d = r->mid() < o->key() ? 0 : 1;
  insert(o->ch[d], r);
  o->maintain();
  if (o->ch[d]->fix < o->fix) rotate(o, d);
}
void remove(Node *&o, double key) {
  double tmp = o->key();
  int d = key < o->key() ? 0 : 1;
  if (o->key() == key) {
    if (o->ch[0] == null)
      o = o->ch[1];
    else if (o->ch[1] == null)
      o = o->ch[0];
    else {
      int d = o->ch[0]->fix < o->ch[1]->fix ? 0 : 1;
      rotate(o, d), remove(o->ch[d ^ 1], key);
    }
  } else
    remove(o->ch[d], key);
  if (o != null) o->maintain();
}
void init(int n) {
  pis = pool;
  null = newnode(sgt::null);
  null->ch[0] = null->ch[1] = null;
  null->sz = 0;
  for (int i = 1; i <= n; i++) {
    root[i] = null;
  }
}
int rank(int r, double key) {
  Node *o = root[r];
  int res = 0;
  while (o != null) {
    double tmp = o->key();
    if (o->key() < key) {
      res += o->ch[0]->sz + 1;
      o = o->ch[1];
    } else
      o = o->ch[0];
  }
  return res;
}
void insert(int x, sgt::Node *r) { insert(root[x], r); }
void remove(int r, double key) { remove(root[r], key); }
void debug(Node *o) {
  if (o == null) return;
  debug(o->ch[0]);
  printf("%.3f, ", o->key());
  debug(o->ch[1]);
}
void debug(int n) {
  for (int i = 1; i <= n; i++) {
    printf("%d : ", i);
    debug(root[i]), puts("");
  }
}
}  // namespace treap
int main() {
  int n, x;
  while (scanf("%d", &n) == 1) {
    sgt::init();
    treap::init(n);
    sgt::cache.clear();
    for (int i = 0; i < n; i++) {
      scanf("%d", &x);
      sgt::Node *o = sgt::newnode(0, 0, x);
      treap::insert(x, o);
      sgt::cache.push_back(o);
    }
    sgt::divide(sgt::root, sgt::cache.da, 0, n - 1, 0, 1);
    int m, opt, l, r, k, last_ans = 0;
    scanf("%d", &m);
    for (int i = 1; i <= m; i++) {
      if (i == 5) {
        int debug = 1;
      }
      scanf("%d%d%d", &opt, &l, &r);
      l = (l + last_ans - 1) % n + 1;
      r = (r + last_ans - 1) % n + 1;
      if (l > r) swap(l, r);
      if (opt == 1) {
        sgt::Node *orisgt = sgt::remove(sgt::root, r);
        sgt::Node *newsgt = sgt::insert(l - 1, orisgt->key);
        treap::remove(orisgt->key, orisgt->mid());
        treap::insert(orisgt->key, newsgt);
        sgt::rebuild();
      } else {
        scanf("%d", &k);
        k = (k + last_ans - 1) % n + 1;
        double keyL = sgt::root->kth(l),
               keyR = r == n ? 1 : sgt::root->kth(r + 1);
        last_ans = treap::rank(k, keyR);
        last_ans -= treap::rank(k, keyL);
        printf("%d\n", last_ans);
      }
    }
  }
  return 0;
}