#include <bits/stdc++.h>   using namespace std;   const int N = 1e5 + 5;   const double alpha = 0.9;   struct Node {     int size, key, nodeCount;     bool isExist;     Node *lc, *rc;     unordered_map<int, int> mp;     bool isBad() {       return lc->nodeCount > alpha * nodeCount + 5 ||              rc->nodeCount > alpha * nodeCount + 5;     }     void merge() {       size = isExist;       size += lc->size;       size += rc->size;       nodeCount = 1;       nodeCount += lc->nodeCount;       nodeCount += rc->nodeCount;       mp.clear();       for (auto e : lc->mp) {         mp[e.first] += e.second;       }       for (auto e : rc->mp) {         mp[e.first] += e.second;       }       if (isExist) mp[key]++;     }   } pool[N * 2], *C = pool + 1, *root, *null;   Node *newNode(int key) {     C->size = 1;     C->key = key;     C->mp.clear();     C->mp[key] = 1;     C->isExist = 1;     C->lc = C->rc = null;     return C++;   }   int n, q;   Node *buildTree(int *a, int l, int r) {     if (l >= r) return null;     int mid = (l + r) / 2;     Node *p = newNode(a[mid]);     p->lc = buildTree(a, l, mid);     p->rc = buildTree(a, mid + 1, r);     p->merge();     return p;   }   void dfs(Node *p, vector<Node *> &v) {     if (p == null) return;     dfs(p->lc, v);     v.push_back(p);     dfs(p->rc, v);   }   Node *divide(vector<Node *> &v, int l, int r) {     if (l >= r) return null;     int mid = (l + r) / 2;     Node *p = v[mid];     p->lc = divide(v, l, mid);     p->rc = divide(v, mid + 1, r);     p->merge();     return p;   }   void rebuild(Node *&p) {     vector<Node *> v;     dfs(p, v);     p = divide(v, 0, v.size());   }   int erase(Node *p, int idx) {     if (p->isExist && idx == p->lc->size + 1) {       p->isExist = 0;       p->mp[p->key]--;       p->size--;       return p->key;     }     int res;     p->size--;     res = idx <= p->lc->size ? erase(p->lc, idx)                              : erase(p->rc, idx - p->lc->size - p->isExist);     p->mp[res]--;     return res;   }   Node **insert(Node *&p, int idx, int val) {     if (p == null) {       p = newNode(val);       return &null;     } else {       p->nodeCount++;       p->size++;       p->mp[val]++;       Node **res = idx <= p->lc->size + 1                        ? insert(p->lc, idx, val)                        : insert(p->rc, idx - p->lc->size - p->isExist, val);       if (p->isBad()) res = &p;       return res;     }   }   int getNumber(Node *p, int l, int r, int w) {     if (p == null) return 0;     if (l <= 1 && p->size <= r) {       return p->mp.count(w) ? p->mp[w] : 0;     } else {       int res = 0;       if (l <= p->lc->size) res += getNumber(p->lc, l, r, w);       if (r > p->lc->size + p->isExist)         res += getNumber(p->rc, l - p->lc->size - p->isExist,                          r - p->lc->size - p->isExist, w);       if (p->isExist && l <= p->lc->size + 1 && p->lc->size + 1 <= r &&           p->key == w) {         res++;       }       return res;     }   }   int main() {     null = pool;     null->size = 0;     null->nodeCount = 0;     null->key = 0;     null->mp.clear();     null->isExist = 0;     null->lc = null->rc = null;     static int a[N];     int lastans = 0;     scanf( %d , &n);     for (int i = 0; i < (int)(n); i++) {       scanf( %d , &a[i]);     }     root = buildTree(a, 0, n);     scanf( %d , &q);     for (int i = 0; i < (int)(q); i++) {       int op, l, r, w;       scanf( %d%d%d , &op, &l, &r);       l = (l + lastans - 1 + n) % n + 1;       r = (r + lastans - 1 + n) % n + 1;       if (l > r) swap(l, r);       if (op == 1) {         int value = erase(root, r);         Node **p = insert(root, l, value);         if (*p != null) rebuild(*p);       } else if (op == 2) {         scanf( %d , &w);         w = (w + lastans - 1 + n) % n + 1;         lastans = getNumber(root, l, r, w);         printf( %d n , lastans);       }     }     return 0;   }