#pragma GCC optimize("-O3")
#include <iostream>
#include <stdio.h>
#include <math.h>
#define block 254
#define MAXD 400
#define MAXN 100010 + MAXD
#define Merge( p , a , b ) if( V[p][a].root ) merge( p , a , b )
#define l( x ) ( x * block - block+1 )
#define r( x ) ( x * block )
using namespace std;
int n , m , belong[ MAXN ] , a[ MAXN ];
int pre[ MAXN ] , pos[ MAXN ] , L[ MAXN ] , R[ MAXN ];
struct point{int num , root;} V[ MAXD ][ MAXN ];
inline void merge( int p , int a , int b ){
	register point x = V[p][a] , y = V[p][b];
	y.root ? pre[ x.root] = y.root : ( y.root = x.root , pos[ y.root  ] = b );
	y.num += x.num , * ( short * ) & x = 0;
	V[p][a] = x , V[p][b] = y;
}
inline int find( int x ){
	while( x != pre[x] ) x = pre[x] = pre[ pre[x] ];
	return x;
}
inline void pushdown( int v ){   
    for( register int i = l( v ) ; i <= r( v ) ; i++ )
		a[i] =pos[find(i)],V[v][a[i]].root=0,V[v][ a[i] ].num=0,a[i]-=L[v];
	for( register int i = l( v ) ; i <= r( v ) ; i++ )  pre[i] = 0; 
	L[v] = 0;
}
inline void update( int v ){
	R[v] = 0;
	for( register int i = l( v ) ; i <= r( v ) ; i++ )
	{
		if( a[i] > R[v] ) R[v] = a[i];
		if( !V[v][ a[i] ].root ) pre[i] = i , V[v][ a[i] ].root =i, 
		pos[i] = a[i];
		else pre[i] = V[v][ a[i] ].root ;
		V[v][ a[i] ].num++;
	}
}
inline void modify( int x , int v ){
	int & p = L[x] , & q = R[x];
	if( v * 2 <= q - p )
	{
		for( register int i = p + 1 ; i <= p + v ; i++ )
			Merge( x , i , i + v );
		p += v;
	}
	else
	{
		for( register int i = q ; i > p + v ; i-- )
			Merge( x , i , i - v );
		q = min( q , p + v );
	}
}
inline void modify( int x , int y , int v )
{
	int p = belong[x] , q = belong[y];
	if( p == q )
	{
		pushdown( p );
		for( register int i = x ; i <= y ; i++ )
			if( a[i] > v )
				a[i] -= v;
		update( p );
	}
	else
	{
		pushdown( p ) , pushdown( q );
		for( register int i = x ; i <= r( p ) ; i++ )
			if( a[i] > v )
				a[i] -= v;
		for( register int i = l( q ) ; i <= y ; i++ )
			if( a[i] > v )
				a[i] -= v;
		for( int i = p + 1 ; i <= q - 1 ; i++ )
			modify( i , v );
		update( p ) , update( q );
	}
}
inline int find( int x , int y , int v )
{
	int ans = 0 , p = belong[x] , q = belong[y];
	if( p == q )
		for( register int i = x ; i <= y ; i++ )
			if( pos[ find( i ) ] - L[ p ] == v )
				ans++;
			else;
	else
	{
		for( register int i = x ; i <= r( p ) ; i++ )
			if( pos[ find( i ) ] - L[ p ] == v )
				ans++;
			else;
		for( register int i = l( q ) ; i <= y ; i++ )
			if( pos[ find( i ) ] - L[ q ] == v )
				ans++;
		for( register int i = p + 1 ; i <= q - 1 ; i++ )
			if( v + L[i] <= 100000 )
				ans += V[i][ v + L[i] ].num;
	}
	return ans;
}
#define sight(c) ('0'<=c&&c<='9')

inline int read(){
    static char c;static int x;
    for (c=getchar();!sight(c);c=getchar());
    for (x=0;sight(c);c=getchar())x=x*10+c-48;return x;
}
void write(int x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
inline void writeln(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('\n'); }
int main()
{
//	freopen("e.in","r",stdin);
//	freopen("ee.out","w",stdout);
	n = read() , m = read();
	for( register int i = 1 ; i <= n ; i++ ) a[i] = read() , belong[i] = ( i - 1 ) / block + 1;
	for( int i = 1 ; i <= belong[n] ; i++ ) update( i );
	while( m-- )
	{
		int opt = read() , l = read() , r = read() , v = read();
		if( opt == 1 ) modify( l , r , v );
		else writeln( find( l , r , v ));
	}
	return 0;
}