RT,看到其他被卡常数的都是六七十/ll
快读快写好像没什么用,开 O2 更慢了(
想知道自己是不是写了什么很慢的东西。
目前最后一发提交的代码:
#include<bits/stdc++.h>
using namespace std;
const int maxv=1e5+10;
const int maxn=1e6+10;
const int maxm=5e5+10;
const int maxB=1005;
int B;
int n,m;
int res[maxm];
int a[maxn],K,tag;
int L[maxB],R[maxB];
int cnt[maxn],fa[maxn],rt[maxn],rtv[maxn];
struct node{
int id,op,x,y,v;
}tmp,q[maxm];
int get(int x){ return (x+B-1)/B; }
int fd(int x){ return (x==fa[x])?x:fa[x]=fd(fa[x]); }
void build(int bl)
{
K=tag=0;
memset(rt,0,sizeof(rt));
memset(cnt,0,sizeof(cnt));
memset(rtv,0,sizeof(rtv));
for(int i=L[bl];i<=R[bl];i++)
{
K=max(K,a[i]);
if(rt[a[i]]==0) rt[a[i]]=fa[i]=i,rtv[i]=a[i];
else fa[i]=rt[a[i]];
cnt[a[i]]++;
}
}
void update_t(int bl,int v)//整块修改
{
if(K<=v) return;//调试
if(K-tag>2*v){
for(int i=tag+1;i<=tag+v;i++)
if(rt[i])
{
int nw=i+v;
cnt[nw]+=cnt[i],cnt[i]=0;
if(rt[nw]==0) rt[nw]=rt[i],rtv[rt[nw]]=nw;
else fa[rt[i]]=rt[nw];
rt[i]=0;
}
tag+=v;
}else{
for(int i=v+1;i<=K;i++)
{
if(rt[i]==0) continue;
int nw=i-v;
cnt[nw]+=cnt[i],cnt[i]=0;
if(rt[nw]==0) rt[nw]=rt[i],rtv[rt[nw]]=nw;
else fa[rt[i]]=rt[nw];
rt[i]=0;
}
}
}
void update_p(int bl,int l,int r,int v)//块的部分修改
{
for(int i=L[bl];i<=R[bl];i++) a[i]=rtv[fd(i)]-tag;
for(int i=l;i<=r;i++) if(a[i]>v) a[i]-=v;
build(bl);
}
int query_t(int bl,int v){ return cnt[v+tag]; }
int query_p(int bl,int l,int r,int v)
{
int ct=0;
for(int i=l;i<=r;i++) if(rtv[fd(i)]-tag==v) ct++;
return ct;
}
signed main()
{
scanf("%d%d",&n,&m);B=sqrt(n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d%d%d%d",&q[i].op,&q[i].x,&q[i].y,&q[i].v),q[i].id=i;
for(int bl=1;bl<=get(n);bl++) L[bl]=(bl-1)*B+1,R[bl]=bl*B;
R[get(n)]=n;
for(int bl=1;bl<=get(n);bl++)
{
build(bl);
for(int t=1;t<=m;t++)
{
if(q[t].x>R[bl]||q[t].y<L[bl]) continue;
tmp=q[t],tmp.x=max(tmp.x,L[bl]),tmp.y=min(tmp.y,R[bl]);
if(tmp.op==1){
if(tmp.x==L[bl]&&tmp.y==R[bl]) update_t(bl,tmp.v);
else update_p(bl,tmp.x,tmp.y,tmp.v);
}else{
if(tmp.x==L[bl]&&tmp.y==R[bl]) res[t]+=query_t(bl,tmp.v);
else res[t]+=query_p(bl,tmp.x,tmp.y,tmp.v);
}
}
}
for(int i=1;i<=m;i++) if(q[i].op==2) printf("%d\n",res[i]);
return 0;
}