感觉不应该这么慢吧?
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
inline void out(int x){
if(x==0){putchar('0');return;}
int len=0,k1=x,c[10005];
if(k1<0)k1=-k1,putchar('-');
while(k1)c[len++]=k1%10+'0',k1/=10;
while(len--)putchar(c[len]);
}
const int N=5e5+5,M=1e3+5,NM=1e6+10;
int ans[N],a[NM],st[M],ed[M],pos[NM],cnt[NM],s[NM],rt[NM],rtv[NM];
int K,tag;
struct node{
int op,x,y,v;
}q[N];
int find(int x){
if(x!=s[x])s[x]=find(s[x]);
return s[x];
}
inline void build(int x){
K=tag=0;
memset(rt,0,sizeof(rt));
memset(cnt,0,sizeof(cnt));
memset(rtv,0,sizeof(rtv));
for(int i=st[x];i<=ed[x];i++){
K=max(K,a[i]);
if(!rt[a[i]])rt[a[i]]=s[i]=i,rtv[i]=a[i];
else s[i]=rt[a[i]];
cnt[a[i]]++;
}
}
inline void upd1(int x){
if(K-tag>2*x){
for(int i=tag+1;i<=tag+x;i++){
if(rt[i]){
int nw=i+x;
cnt[nw]+=cnt[i],cnt[i]=0;
if(rt[nw]==0)rt[nw]=rt[i],rtv[rt[nw]]=nw;
else s[rt[i]]=rt[nw];
rt[i]=0;
}
}
tag+=x;
}
else{
for(int i=x+1;i<=K;i++){
if(rt[i]==0)continue;
int nw=i-x;
cnt[nw]+=cnt[i],cnt[i]=0;
if(rt[nw]==0)rt[nw]=rt[i],rtv[rt[nw]]=nw;
else s[rt[i]]=rt[nw];
rt[i]=0;
}
}
}
inline void upd2(int x,int l,int r,int v){
for(int i=st[x];i<=ed[x];i++)a[i]=rtv[find(i)]-tag;
for(int i=l;i<=r;i++){
if(a[i]>v)a[i]-=v;
}
build(x);
}
inline int query1(int x){
return cnt[x+tag];
}
inline int query2(int l,int r,int x){
int cnt=0;
for(int i=l;i<=r;i++){
if(rtv[find(i)]-tag==x)cnt++;
}
return cnt;
}
signed main(){
int n=read(),m=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=m;i++)q[i].op=read(),q[i].x=read(),q[i].y=read(),q[i].v=read();
int block=sqrt(n),t=n/block;
for(int i=1;i<=t;i++){
st[i]=(i-1)*block+1;
ed[i]=i*block;
}
ed[t]=n;
for(int i=1;i<=n;i++)pos[i]=(i-1)/block+1;
for(int i=1;i<=t;i++){
build(i);
for(int j=1;j<=m;j++){
if(q[j].x>ed[i]||q[j].y<st[i])continue;
int l=max(q[j].x,st[i]),r=min(q[j].y,ed[i]),v=q[j].v,op=q[j].op;
if(op==1){
if(l==st[i]&&r==ed[i])upd1(v);
else upd2(i,l,r,v);
}
else{
if(l==st[i]&&r==ed[i])ans[j]+=query1(v);
else ans[j]+=query2(l,r,v);
}
}
}
for(int i=1;i<=m;i++) {
if(q[i].op==2)out(ans[i]),puts("");
}
return 0;
}