#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
int a[100010];
int n,m;
struct seg{//楼房重建(pushup(log)),解决计算前缀下最小值/最大值位置数量问题
#define mx(x) tr[x].mx
#define num(x) tr[x].num
#define tag1(x) tr[x].tag1
#define tag2(x) tr[x].tag2
struct node{
int mx;int num;//num(x)表示只考虑这一段(l,r)时的答案
int tag1;int tag2;
}tr[400010];
void build(int p,int l,int r,vector<int>& ve){
mx(p)=num(p)=tag1(p)=tag2(p)=0;
if(l==r){
mx(p)=ve[l];num(p)=1;
return ;
}
int mid=(l+r)>>1;
build(p<<1,l,mid,ve);build(p<<1|1,mid+1,r,ve);
}
void pushup1(int p){
mx(p)=max(mx(p<<1),mx(p<<1|1));
}
int pushup2(int p,int l,int r,int len){
if(l==r) return mx(p)>len;
spread(p);
if(mx(p)<=len) return 0;
int mid=(l+r)>>1;
if(mx(p<<1|1)>len) return num(p)-num(p<<1|1)+pushup2(p<<1|1,mid+1,r,len);
else return pushup2(p<<1,l,mid,len);
}
void spread(int p){
tag1(p<<1)+=tag1(p),tag1(p<<1|1)+=tag1(p);
mx(p<<1)+=tag1(p);mx(p<<1|1)+=tag1(p);
tag1(p)=0;
if(tag2(p)){
mx(p<<1)=tag2(p),mx(p<<1|1)=tag2(p);
tag2(p<<1)=tag2(p),tag2(p<<1|1)=tag2(p);
tag2(p)=0;
}
}
int get(int p,int l,int r){
int mid=(l+r)>>1;spread(p);
return num(p<<1|1)+((mx(p<<1)<=mx(p<<1|1))?0:pushup2(p<<1,l,mid,mx(p<<1|1)));
}
void modify(int p,int l,int r,int L,int R,int ad,int t){//0覆盖,1加法
if(l!=r) spread(p);
if(L<=l&&r<=R){
if(t==0) {tag2(p)=ad;mx(p)=ad,num(p)=1;}
else {
tag1(p)+=ad;
mx(p)+=ad;
}
return ;
}
int mid=(l+r)>>1;
if(mid>=L) modify(p<<1,l,mid,L,R,ad,t);
if(mid<R) modify(p<<1|1,mid+1,r,L,R,ad,t);
pushup1(p);
num(p)=get(p,l,r);
}
void modify(int l,int r,int num,int t){
modify(1,1,n,l,r,num,t);
}
int queryL(int p,int l,int r,int L,int R,int nz){
if(l==r){
return mx(p)>nz?l:-1;
}
spread(p);
int mid=(l+r)>>1;
if(mid<R){
int t=queryL(p<<1|1,mid+1,r,L,R,nz);
if(t!=-1) return t;
}
return queryL(p<<1,l,mid,L,R,nz);
}
int queryL(int pz,int num){//pz左边第一个比它大的位置
if(pz==1) return -1;
return queryL(1,1,n,1,pz-1,num);
}
int ask(int p,int l,int r,int L,int R){
if(L<=l&&r<=R) return mx(p);
spread(p);
int mid=(l+r)>>1;
if(mid>=L&&mid<R) return max(ask(p<<1,l,mid,L,R),ask(p<<1|1,mid+1,r,L,R));
if(mid>=L) return ask(p<<1,l,mid,L,R);
if(mid<R) return ask(p<<1|1,mid+1,r,L,R);
return -1;
}
int ask(int l,int r){
return ask(1,1,n,l,r);
}
int query_stack_num(int p,int l,int r,int L,int R,int nz){
if(L<=l&&r<=R) return pushup2(p,l,r,nz);
int mid=(l+r)>>1;
if(mid>=L&&mid<R) {
int nxtl=max(nz,mx(p>>1|1));
return max(query_stack_num(p<<1,l,mid,L,R,nxtl),query_stack_num(p<<1|1,mid+1,r,L,R,nz));
}
if(mid>=L) return query_stack_num(p<<1,l,mid,L,R,nz);
if(mid<R) return query_stack_num(p<<1|1,mid+1,r,L,R,nz);
return -1;
}
int query_stack_num(int l,int r,int nz){
return query_stack_num(1,1,n,l,r,nz);
}
};
seg sg;
void solve(){
cin>>n>>m;
vector<int> a(n+1);
for(int i=1;i<=n;i++){
cin>>a[i];
}
struct node{
int op,l,r,x;
};
vector<node> ak(m+1);
vector<int> ans(m+1,0);
for(int i=1;i<=m;i++){
cin>>ak[i].op>>ak[i].l>>ak[i].r>>ak[i].x;
}
auto ope=[&](vector<int>& ve,vector<node>& qry)->void {
sg.build(1,1,n,ve);
for(int i=1;i<=m;i++){
auto [op,l,r,x]=qry[i];
if(op==1){
sg.modify(l,r,x,1);
}
else if(op==2){
sg.modify(l,r,x,0);
}
else if(l!=-1){
int w=sg.ask(x,x);
int pz=sg.queryL(x,w);
ans[i]+=max(r-max(l,pz)+1,0);
if(pz>l) ans[i]+=sg.query_stack_num(l,min(r,pz-1),sg.ask(pz,pz));
}
}
};
vector<node> qry1(m+1),qry2(m+1);
for(int i=1;i<=m;i++){
if(ak[i].op!=3) qry1[i]=qry2[i]=ak[i];
else{
auto [op,l,r,x]=ak[i];
if(x<=r&&x>=l) {
ans[i]++;
qry1[i]={3,l,x-1,x};
qry2[i]={3,x+1,r,x};
}
else if(x<l){
qry1[i]={3,-1,-1,x};
qry2[i]={3,l,r,x};
}
else{
qry1[i]={3,l,r,x};
qry2[i]={3,n+2,n+2,x};
}
}
}
for(auto& [op,l,r,x]:qry2){
l=n-l+1,r=n-r+1;swap(l,r);
if(op==3) x=n-x+1;
}
ope(a,qry1);
reverse(a.begin()+1,a.end());
ope(a,qry2);
for(int i=1;i<=m;i++){
if(ak[i].op==3) cout<<ans[i]<<'\n';
}
}
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
cout << setiosflags(ios::fixed) << setprecision(15);
int _ = 1;
cin >> _;
while (_--) solve();
return 0;
}
/*
1
10 2
1 3 2 5 2 3 1 6 4 5
1 1 5 2
2 8 8 8
*/
/*
1
10 10
1 3 2 5 2 3 1 6 4 5
3 5 7 8
3 5 7 4
1 1 5 2
3 1 10 4
3 1 10 8
2 8 8 8
3 1 10 8
3 1 10 4
2 4 8 1
3 1 2 10
*/