我在条第二分块,可我提交一直 TLE+RE,我坚信我的代码效率没问题,所以去洛谷IDE运行样例,结果开O2 TLE,不开O2 RE。本地测试除了被一些特判 0 的hack WA了,没有找到其他问题。
这是我的代码:
#include<bits/stdc++.h>
#define rd read()
#define gc getchar()
using namespace std;
const int S=1005,M=500005,N=1000005,V=100005;
inline int read()
{
unsigned int x=0,s=gc;
while(s<'0'||s>'9')s=gc;
while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+(s^48),s=gc;
return x;
}
struct ques{int op,l,r,x;}qr[M];
int n,q,val[N],lazy,mx;
int a[N],block,tot;
int L[S],R[S],ans[M];
int siz[V],fa[N],nam[V];
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline int merge(int x,int y)
{
if(nam[y])fa[nam[x]]=nam[y];
else val[nam[y]=nam[x]]=y;
siz[y]+=siz[x];
nam[x]=siz[x]=0;
}
inline void build(int x)
{
lazy=0,mx=INT_MIN;
for(int i=L[x];i<=R[x];i++)
{
mx=max(mx,a[i]);
if(!nam[a[i]])val[i]=a[i],nam[a[i]]=i,fa[i]=i;
else fa[i]=nam[a[i]];
++siz[a[i]];
}
}
inline void alchange(int x)
{
if(x*2>mx-lazy)
{
for(int i=mx;i>x+lazy;i--)if(nam[i])merge(i,i-x);
mx=min(mx,x+lazy);
return;
}
for(int i=lazy+1;i<=lazy+x;i++)if(nam[i])merge(i,i+x);
lazy+=x;
}
inline void change(int id,int l,int r,int x)
{
l=max(l,L[id]),r=min(r,R[id]);
for(int i=L[id],w;i<=R[id];i++)
{
w=val[find(i)];
a[i]=w-lazy,siz[w]=nam[w]=0;
}
for(int i=L[id];i<=R[id];i++)val[i]=0;
for(int i=l;i<=r;i++)if(a[i]>x)a[i]-=x;
build(id);
}
inline int ask(int id,int l,int r,int x)
{
int ans=0;
l=max(l,L[id]),r=min(r,R[id]);
for(int i=l;i<=r;i++)if(val[find(i)]-lazy==x)++ans;
return ans;
}
inline void solve()
{
for(int i=1;i<=tot;i++)
{
if(i>1)memset(siz,0,sizeof(siz)),memset(fa,0,sizeof(fa));
build(i);
for(int j=1;j<=q;j++)
{
if(L[i]>qr[j].r||R[i]<qr[j].l)continue;
if(qr[j].op==1)
{
if(qr[j].l<=L[i]&&qr[j].r>=R[i])alchange(qr[j].x);
else change(i,qr[j].l,qr[j].r,qr[j].x);
}
else if(qr[j].x+lazy<=mx)
{
if(qr[j].l<=L[i]&&qr[j].r>=R[i])ans[j]+=siz[qr[j].x+lazy];
else ans[j]+=ask(i,qr[j].l,qr[j].r,qr[j].x);
}
}
}
}
signed main()
{
n=rd,q=rd;block=sqrt(n),tot=n/block+(n%block?1:0);
for(int i=1;i<=n;i++)a[i]=rd;
for(int i=1;i<=q;i++)qr[i]={rd,rd,rd,rd};
for(int i=1;i<=tot;i++)L[i]=R[i-1]+1,R[i]=i*block;
R[tot]=n,solve();
for(int i=1;i<=q;i++)if(qr[i].op==2)cout<<ans[i]<<'\n';
return 0;
}