由于晚上比赛二连(Atcoder&codeforces),外加复习学考,所以暂时没时间写了。
贴个O(n√n)的分块代码,洛谷和cf上都过了,但垃圾bzoj卡不过去,反正分块题也没什么卡头的就不改了。
#include<bits/stdc++.h> using namespace std; const int N=1e5+7; int n,m,B,a[N],b[N],pos[N],l[N],r[N],fa[N],mx[N],sum[N],c[320][N],tag[N]; int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} void build(int id) { for(int i=l[id];i<=r[id];i++)a[i]=b[find(i)],c[id][a[i]]=0; for(int i=l[id];i<=r[id];i++)fa[i]=i,sum[i]=1; for(int i=l[id];i<=r[id];i++) if(!c[id][a[i]])c[id][a[i]]=i,b[i]=a[i]; else sum[c[id][a[i]]]+=sum[i],fa[i]=c[id][a[i]]; while(!c[id][mx[id]])mx[id]--; } void update(int id,int x,int y,int v) { for(int i=l[id];i<=r[id];i++)a[i]=b[find(i)]; for(int i=l[id];i<=r[id];i++)c[id][a[i]]=0; for(int i=x;i<=y;i++)if(b[find(i)]-tag[id]>v)a[i]-=v; for(int i=l[id];i<=r[id];i++)b[i]=a[i],fa[i]=i; build(id); } void modify(int x,int y,int v) { if(pos[x]==pos[y]){update(pos[x],x,y,v);return;} update(pos[x],x,r[pos[x]],v),update(pos[y],l[pos[y]],y,v); for(int i=pos[x]+1;i<pos[y];i++) if(v<mx[i]-tag[i]&&mx[i]-tag[i]<2*v) { for(int j=tag[i]+v+1;j<=mx[i];j++) if(c[i][j]) if(!c[i][j-v])c[i][j-v]=c[i][j],b[c[i][j]]=j-v,c[i][j]=0; else fa[c[i][j]]=c[i][j-v],sum[c[i][j-v]]+=sum[c[i][j]],c[i][j]=0; while(!c[i][mx[i]])mx[i]--; } else if(mx[i]-tag[i]>=2*v) { for(int j=tag[i]+1;j<=tag[i]+v;j++) if(c[i][j]) if(!c[i][j+v])c[i][j+v]=c[i][j],b[c[i][j]]=j+v,c[i][j]=0; else fa[c[i][j]]=c[i][j+v],sum[c[i][j+v]]+=sum[c[i][j]],c[i][j]=0; tag[i]+=v; } } int query(int x,int y,int v) { int ret=0; if(pos[x]==pos[y]) { for(int i=x;i<=y;i++)if(b[find(i)]-tag[pos[i]]==v)ret++; return ret; } for(int i=x;i<=r[pos[x]];i++)if(b[find(i)]-tag[pos[i]]==v)ret++; for(int i=l[pos[y]];i<=y;i++)if(b[find(i)]-tag[pos[i]]==v)ret++; for(int i=pos[x]+1;i<pos[y];i++)if(v+tag[i]<N)ret+=sum[c[i][v+tag[i]]]; return ret; } int main() { scanf("%d%d",&n,&m),B=sqrt(n); for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i],fa[i]=i; for(int i=1;i<=n;i++) { r[pos[i]=(i-1)/B+1]=i; if(!l[pos[i]])l[pos[i]]=i; } for(int i=1;i<=pos[n];i++)mx[i]=1e5,build(i); while(m--) { int op,x,y,v;scanf("%d%d%d%d",&op,&x,&y,&v); if(op==1)modify(x,y,v);else printf("%d\n",query(x,y,v)); } }View Code