http://www.lydsy.com/JudgeOnline/problem.php?id=3343
high记录原始身高
HIGH记录每块排序之后的身高
不满一块的直接对high操作,重排之后再赋值给HIGH
块内直接打标记
查询时,不满一块的直接查,一整块的在HIGH内二分块内第一个>=C-标记的点
#include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 1000001 int bl[N]; int high[N],HIGH[N],tmp[N]; int L[1001],R[1001],tag[1001]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } void modify(int l,int r,int w) { if(bl[l]==bl[r]) { for(int i=l;i<=r;++i) high[i]+=w; for(int i=L[bl[l]];i<=R[bl[l]];++i) tmp[i]=high[i]; sort(tmp+L[bl[l]],tmp+R[bl[l]]+1); for(int i=L[bl[l]];i<=R[bl[l]];++i) HIGH[i]=tmp[i]; return; } for(int i=l;i<=R[bl[l]];++i) high[i]+=w; for(int i=L[bl[l]];i<=R[bl[l]];++i) tmp[i]=high[i]; sort(tmp+L[bl[l]],tmp+R[bl[l]]+1); for(int i=L[bl[l]];i<=R[bl[l]];++i) HIGH[i]=tmp[i]; for(int i=L[bl[r]];i<=r;++i) high[i]+=w; for(int i=L[bl[r]];i<=R[bl[r]];++i) tmp[i]=high[i]; sort(tmp+L[bl[r]],tmp+R[bl[r]]+1); for(int i=L[bl[r]];i<=R[bl[r]];++i) HIGH[i]=tmp[i]; for(int i=bl[l]+1;i<bl[r];++i) tag[i]+=w; } int find(int x,int y,int w) { int l=x,r=y,mid,ok=y+1; while(l<=r) { mid=l+r>>1; if(HIGH[mid]>=w) ok=mid,r=mid-1; else l=mid+1; } return y-ok+1; } void ask(int l,int r,int w) { int ans=0; if(bl[l]==bl[r]) { for(int i=l;i<=r;++i) if(high[i]+tag[bl[l]]>=w) ans++; cout<<ans<<' '; return; } for(int i=l;i<=R[bl[l]];++i) if(high[i]+tag[bl[l]]>=w) ans++; for(int i=L[bl[r]];i<=r;++i) if(high[i]+tag[bl[r]]>=w) ans++; for(int i=bl[l]+1;i<bl[r];++i) ans+=find(L[i],R[i],w-tag[i]); cout<<ans<<' '; } int main() { int n,m; read(n); read(m); for(int i=1;i<=n;++i) { read(high[i]); HIGH[i]=high[i]; } int siz=sqrt(n); for(int i=1;i<=n;++i) bl[i]=(i-1)/siz+1; for(int i=1;i<=bl[n];++i) { L[i]=R[i-1]+1; R[i]=L[i]+siz-1; } R[bl[n]]=n; for(int i=1;i<=bl[n];++i) sort(HIGH+L[i],HIGH+R[i]+1); char s[3]; int l,r,w; while(m--) { scanf("%s",s); read(l); read(r); read(w); if(s[0]=='M') modify(l,r,w); else ask(l,r,w); } return 0; }