rt,#8死活过不去
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int N=1e6;
const int M=5e5;
const int C=1e5;
const int K=800;
int num[2*C+5],fa[N+5],sz[N+5];
inline int Find(int x){
if(fa[x]==x){
return x;
}
return fa[x]=Find(fa[x]);
}
inline void merge(int x,int y){
if(x!=y){
fa[x]=y;
sz[y]+=sz[x];
}
}
struct Query{
int type;
int l,r,x;
int ansid;
}q[M+5];
int n,m,a[N+5],pos[N+5],L[K+5],R[K+5],maxn,tag;
inline void init(int p){
memset(num,0,sizeof num);
memset(sz,0,sizeof sz);
maxn=tag=0;
for(int i=L[p];i<=R[p];i++){
fa[i]=i;sz[i]=1;
if(!num[a[i]]){
num[a[i]]=i;
}else{
merge(i,num[a[i]]);
}
maxn=max(maxn,a[i]);
}
}
inline void update(int p,int qid){
int l=q[qid].l,r=q[qid].r,x=q[qid].x;
if(l<=L[p]&&r>=R[p]){
if(maxn>x+x){
for(int i=tag+x;i>=tag;i--){
if(!num[i]){
continue;
}
if(!num[i+x]){
swap(num[i],num[i+x]);
a[num[i+x]]=i+x;
}else{
merge(num[i],num[i+x]);
num[i]=0;
}
}
tag+=x;maxn-=x;
}else{
for(int i=tag+x+1;i<=tag+maxn;i++){
if(!num[i]){
continue;
}
if(!num[i-x]){
swap(num[i],num[i-x]);
a[num[i-x]]=i-x;
}else{
merge(num[i],num[i-x]);
num[i]=0;
}
}
maxn=min(maxn,x);
}
}else if(!(r<L[p]||l>R[p])){
for(int i=L[p];i<=R[p];i++){
a[i]=a[Find(i)];
}
for(int i=L[p];i<=R[p];i++){
if(a[i]-tag<=x){
continue;
}
num[a[i]]=0;
sz[i]=0;
}
for(int i=L[p];i<=R[p];i++){
if(a[i]-tag<=x){
continue;
}
if(i>=l&&i<=r){
a[i]-=x;
}
fa[i]=i;sz[i]=1;
if(!num[a[i]]){
num[a[i]]=i;
}else{
merge(i,num[a[i]]);
}
}
maxn=0;
for(int i=L[p];i<=R[p];i++){
maxn=max(maxn,a[i]-tag);
}
}else{
return;
}
while(!num[tag+maxn]||!sz[num[tag+maxn]]){
maxn--;
}
}
inline int query(int p,int qid){
int l=q[qid].l,r=q[qid].r,x=q[qid].x,res=0;
if(l<=L[p]&&r>=R[p]){
return (num[tag+x]>0)?sz[num[tag+x]]:0;
}else if(!(r<L[p]||l>R[p])){
for(int i=L[p];i<=R[p];i++){
a[i]=a[Find(i)];
if(a[i]-tag==x&&i>=l&&i<=r){
res++;
}
}
return res;
}
return 0;
}
inline int read(){
char c=getchar();
while(c<'0'||c>'9'){
c=getchar();
}
int x=0;
while(c>='0'&&c<='9'){
x=(x<<1)+(x<<3)+c-'0';
c=getchar();
}
return x;
}
inline void write(int x){
if(!x){
return;
}
write(x/10);
putchar(x%10+'0');
}
int ans[M+5];
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
a[i]=read();
}
int block=max(1250,int(sqrt(n*1.0)));
int num=n/block+(n%block>0);
for(int i=1;i<=num;i++){
L[i]=R[i-1]+1;
R[i]=R[i-1]+block;
}
R[num]=n;
int ansSum=0;
for(int i=1;i<=m;i++){
q[i].type=read();q[i].l=read();q[i].r=read();q[i].x=read();
if(q[i].type==2){
q[i].ansid=++ansSum;
}
}
for(int i=1;i<=num;i++){
init(i);
for(int j=1;j<=m;j++){
if(q[j].type==1){
update(i,j);
}else{
ans[q[j].ansid]+=query(i,j);
}
}
}
for(int i=1;i<=ansSum;i++){
if(!ans[i]){
putchar('0');
}else{
write(ans[i]);
}
putchar('\n');
}
return 0;
}