/*************************************************************************
> File Name: test.cpp
> Author: jiangyuzhu
> Mail: 834138558@qq.com
> Created Time: 2016/7/26 21:06:05
************************************************************************/
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
#include<cmath>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5, oo = 0x3f3f3f3f;
#define lson i << 1
#define rson i << 1 | 1
int a[maxn];
struct Tree{
int l, r;
ll lazy, val;
ll maxx, minn;
}tree[maxn * 4 + 5];
void push_up(int i)
{
tree[i].minn = min(tree[lson].minn, tree[rson].minn);
tree[i].maxx = max(tree[lson].maxx, tree[rson].maxx);
tree[i].val = tree[lson].val + tree[rson].val;
}
void build(int i, int l, int r)
{
tree[i].l = l;
tree[i].r = r;
tree[i].val = 0;
tree[i].lazy = 0;
tree[i].minn = oo;
tree[i].maxx = 0;
if(l == r){
tree[i].val = a[l];
tree[i].maxx = a[l];
tree[i].minn = a[l];
return;
}
int mid = l + r >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
push_up(i);
}
void push_down(int i)
{
if(tree[i].lazy){
tree[lson].lazy += tree[i].lazy;
tree[rson].lazy += tree[i].lazy;
tree[lson].minn += tree[i].lazy;
tree[lson].maxx += tree[i].lazy;
tree[rson].minn += tree[i].lazy;
tree[rson].maxx += tree[i].lazy;
tree[lson].val += tree[i].lazy * (tree[lson].r - tree[lson].l + 1);
tree[rson].val += tree[i].lazy * (tree[rson].r - tree[rson].l + 1);
tree[i].lazy = 0;
}
}
void update(int i, int l, int r, int val)
{
if(tree[i].l == l && tree[i].r == r){
tree[i].lazy += val;
tree[i].maxx += val;
tree[i].minn += val;
tree[i].val += (r - l + 1) * (ll)val;
return;
}
push_down(i);
int mid = tree[i].l + tree[i].r >> 1;
if(r <= mid) update(lson, l, r, val);
else if(l > mid) update(rson, l, r, val);
else{
update(lson, l, mid, val);
update(rson, mid + 1, r, val);
}
push_up(i);
}
void update2(int i, int l, int r)
{
if(tree[i].l >= l && tree[i].r <= r){
if(tree[i].minn == tree[i].maxx){
ll tmp = (ll)sqrt((double)tree[i].minn);
tree[i].lazy -= tree[i].minn - tmp;
tree[i].minn = tmp;
tree[i].maxx = tmp;
tree[i].val = (tree[i].r - tree[i].l + 1) * tmp;
return;
}else if(tree[i].minn == tree[i].maxx - 1){
ll tmp1 = (ll)sqrt((double)tree[i].minn);
ll tmp2 = (ll)sqrt((double)tree[i].maxx);
if(tmp1 == tmp2 - 1){
tree[i].lazy -= tree[i].maxx - tmp2;
tree[i].val -= (tree[i].maxx - tmp2) * (tree[i].r - tree[i].l + 1);
tree[i].minn = tmp1;
tree[i].maxx = tmp2;
return;
}
}
}
push_down(i);
int mid = tree[i].l + tree[i].r >> 1;
if(r <= mid) update2(lson, l, r);
else if(l > mid) update2(rson, l, r);
else{
update2(lson, l, mid);
update2(rson, mid + 1, r);
}
push_up(i);
}
ll query(int i, int l, int r)
{
if(tree[i].l == l && tree[i].r == r){
return tree[i].val;
}
push_down(i);
int mid = tree[i].l + tree[i].r >> 1;
if(r <= mid) return query(lson, l, r);
else if(l > mid) return query(rson, l, r);
else return query(lson, l, mid) + query(rson, mid + 1, r);
}
int main(void)
{
int T;scanf("%d", &T);
while(T--){
int n, m;scanf("%d%d", &n, &m);
for(int i = 0; i < n; i++) scanf("%d", &a[i]);
build(1, 0, n);
int op, l, r, x;
for(int i = 0; i < m; i++){
scanf("%d%d%d", &op, &l, &r);
l--;r--;
if(op == 1){
scanf("%d", &x);
update(1, l, r, x);
}else if(op == 2){
update2(1, l, r);
}else{
printf("%lld\n", query(1, l, r));
}
}
}
return 0;
}