#include <bits/stdc++.h>   using namespace std;   template <class T>   inline void rread(T& num) {     num = 0;     T f = 1;     char ch = getchar();     while (ch <  0  || ch >  9 ) {       if (ch ==  - ) f = -1;       ch = getchar();     }     while (ch >=  0  && ch <=  9 ) num = num * 10 + ch -  0 , ch = getchar();     num *= f;   }   const int maxn = 1e5 + 5, maxpow = 9;   const long long inf = 1e18;   int n, m;   long long a[maxn];   vector<long long> bin;   inline void Prework() {     long long now = 1;     for (int(i) = (0); (i) < (maxpow); (i)++) bin.push_back(now), now *= 42;   }   inline long long GetToNxt(long long x) {     int tmp = lower_bound(bin.begin(), bin.end(), x) - bin.begin();     if (tmp == maxpow) return inf;     return bin[tmp] - x;   }   int root;   namespace Treap {   int ndtot;   struct TreapNode {     int l, r, len, sz;     long long val, tonxt, mini, tag;   } T[maxn];   vector<int> pool;   inline int NewNode(long long val, int len) {     int x;     if (((pool).size()))       x = pool.back(), pool.pop_back();     else       x = ++ndtot;     (T[(x)].l) = (T[(x)].r) = (T[(x)].tag) = 0;     (T[(x)].val) = val;     (T[(x)].sz) = (T[(x)].len) = len;     (T[(x)].tonxt) = (T[(x)].mini) = GetToNxt(val);     return x;   }   inline void Update(int x) {     (T[(x)].sz) = (T[(x)].len) + (T[((T[(x)].l))].sz) + (T[((T[(x)].r))].sz);     (T[(x)].mini) =         min((T[(x)].tonxt), min((T[((T[(x)].l))].mini), (T[((T[(x)].r))].mini)));   }   inline int Build(int l, int r) {     if (l > r) return 0;     int x = NewNode(a[((l + r) >> 1)], 1);     (T[(x)].l) = Build(l, ((l + r) >> 1) - 1);     (T[(x)].r) = Build(((l + r) >> 1) + 1, r);     Update(x);     return x;   }   inline void AddVal(int x, long long num) {     if (!x) return;     (T[(x)].tag) += num;     (T[(x)].val) += num;     (T[(x)].tonxt) -= num;     (T[(x)].mini) -= num;   }   inline void PushDown(int x) {     if (!x || !(T[(x)].tag)) return;     AddVal((T[(x)].l), (T[(x)].tag));     AddVal((T[(x)].r), (T[(x)].tag));     (T[(x)].tag) = 0;   }   inline int Rnd(int x, int y) {     return rand() % ((T[(x)].sz) + (T[(y)].sz)) < (T[(x)].sz);   }   inline int Merge(int x, int y) {     if (!x || !y) return x + y;     PushDown(x);     PushDown(y);     if (Rnd(x, y)) {       (T[(x)].r) = Merge((T[(x)].r), y);       Update(x);       return x;     } else {       (T[(y)].l) = Merge(x, (T[(y)].l));       Update(y);       return y;     }   }   inline pair<int, int> Split(int x, int len) {     if (!x) return make_pair(0, 0);     PushDown(x);     if ((T[((T[(x)].l))].sz) >= len) {       pair<int, int> y = Split((T[(x)].l), len);       (T[(x)].l) = y.second;       Update(x);       return make_pair(y.first, x);     }     len -= (T[((T[(x)].l))].sz);     if (len < (T[(x)].len)) {       int x1 = NewNode((T[(x)].val), len),           x2 = NewNode((T[(x)].val), (T[(x)].len) - len);       (T[(x1)].l) = (T[(x)].l);       (T[(x2)].r) = (T[(x)].r);       Update(x1);       Update(x2);       pool.push_back(x);       return make_pair(x1, x2);     }     len -= (T[(x)].len);     pair<int, int> z = Split((T[(x)].r), len);     (T[(x)].r) = z.first;     Update(x);     return make_pair(x, z.second);   }   inline long long QueryVal(int x) {     long long res;     pair<int, int> b = Split(root, x), a = Split(b.first, x - 1);     res = (T[(a.second)].val);     b.first = Merge(a.first, a.second);     root = Merge(b.first, b.second);     return res;   }   inline void Recycle(int x) {     if (!x) return;     Recycle((T[(x)].l));     pool.push_back(x);     Recycle((T[(x)].r));   }   inline void SetVal(int l, int r, long long val) {     pair<int, int> b = Split(root, r), a = Split(b.first, l - 1);     Recycle(a.second);     int x = NewNode(val, r - l + 1);     b.first = Merge(a.first, x);     root = Merge(b.first, b.second);   }   inline void FixMini(int x) {     if (!x) return;     PushDown(x);     if ((T[(x)].tonxt) == (T[(x)].mini)) {       (T[(x)].tonxt) = GetToNxt((T[(x)].val));       Update(x);       return;     }     if ((T[((T[(x)].l))].mini) < (T[((T[(x)].r))].mini))       FixMini((T[(x)].l));     else       FixMini((T[(x)].r));     Update(x);   }   inline void Print(int x) {     if (!x) return;     Print((T[(x)].l));     cerr << (T[(x)].val) <<  (  << (T[(x)].tonxt) <<  )  ;     Print((T[(x)].r));   }   inline void AddVal(int l, int r, long long x) {     pair<int, int> b = Split(root, r), a = Split(b.first, l - 1);     AddVal(a.second, x);     while (1) {       while ((T[(a.second)].mini) < 0) FixMini(a.second);       if ((T[(a.second)].mini) > 0) break;       AddVal(a.second, x);     }     b.first = Merge(a.first, a.second);     root = Merge(b.first, b.second);   }   inline void Init() { (T[(0)].mini) = inf; }   }  // namespace Treap   inline void judge() {     freopen( input.txt ,  r , stdin);     freopen( output.txt ,  w , stdout);   }   int main() {     Prework();     Treap::Init();     rread(n);     rread(m);     for (int(i) = (1); (i) <= (n); (i)++) rread(a[i]);     root = Treap::Build(1, n);     while (m--) {       int opt;       rread(opt);       if (opt == 1) {         int x;         rread(x);         printf( %lld n , Treap::QueryVal(x));       } else if (opt == 2) {         int l, r;         long long x;         rread(l);         rread(r);         rread(x);         Treap::SetVal(l, r, x);       } else if (opt == 3) {         int l, r;         long long x;         rread(l);         rread(r);         rread(x);         Treap::AddVal(l, r, x);       }     }     return 0;   }