传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3343
思路:分块大法好...
分块,每块内部保持有序。
修改时,给完整的块打标记,两段不完整的暴力改
询问时,给完整的块二分查找,两段不完整的暴力查。
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> const int maxn=1000010,maxk=2010; using namespace std; int n,m,q;char op[5],ch; struct Block{ int a[maxn],b[maxn],add[maxk],pos[maxn],sz; void clear(int x){ int l=(x-1)*sz+1,r=min(x*sz,n); for (int i=l;i<=r;i++) b[i]=a[i]; sort(b+l,b+r+1); } void change(int x,int y,int v){ if (pos[x]==pos[y]) for (int i=x;i<=y;i++) a[i]+=v; else{ for (int i=x;i<=pos[x]*sz;i++) a[i]+=v; for (int i=(pos[y]-1)*sz+1;i<=y;i++) a[i]+=v; } clear(pos[x]),clear(pos[y]); for (int i=pos[x]+1;i<pos[y];i++) add[i]+=v; } int find(int x,int v){ int l=(x-1)*sz+1,r=min(x*sz,n),mid=(l+r)>>1,cnt=r; while (l<=r){ if (b[mid]>=v) r=mid-1; else l=mid+1; mid=(l+r)>>1; } return cnt-l+1; } int query(int x,int y,int v){ int sum=0; if (pos[x]==pos[y]) for (int i=x;i<=y;i++) sum+=(a[i]+add[pos[i]]>=v); else{ for (int i=x;i<=pos[x]*sz;i++) sum+=(a[i]+add[pos[i]]>=v); for (int i=(pos[y]-1)*sz+1;i<=y;i++) sum+=(a[i]+add[pos[i]]>=v); } for (int i=pos[x]+1;i<pos[y];i++) sum+=find(i,v-add[i]); return sum; } }T; void read(int &x){ for (ch=getchar();!isdigit(ch);ch=getchar()); for (x=0;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; } int main(){ scanf("%d%d",&n,&q);T.sz=(int)sqrt(n); for (int i=1;i<=n;i++){ read(T.a[i]),T.pos[i]=(i-1)/T.sz+1; } m=n/T.sz+(n%T.sz?1:0); for (int i=1;i<=m;i++) T.clear(i); for (int i=1,x,y,z;i<=q;i++){ scanf("%s",op);read(x),read(y),read(z); if (op[0]=='M') T.change(x,y,z); else printf("%d\n",T.query(x,y,z)); } return 0; }