分块什么的最好了~(至少简单易懂,代码还比较好写)
这题就当是我学习了分块的flag吧。
其实分块就是把原来n个元素分成sqrt(n)块,每块有sqrt(n)个元素。
对于一段连续的区间修改,我们可以把这个区间分成若干个完整的块和两端剩下的元素。
对于完整的块,我们可以用和线段树一样的思想——延迟标记来记录当前块内所有元素的共同修改量;
对于两端剩下的元素,我们可以暴力修改。(暴力大法好~)
对于询问,我们可以再开一个数组,和之前的数组一样分块,但是要把每个块内的元素排序。
然后我们把询问拆分成若干个完整的块和两端剩下的元素。
对于完整的块,我们可以二分出块内的答案;对于两端剩下的元素,依然是暴力……
综上,这道题就被分块水过去了。(因为询问的次数比较小嘛)
附上AC代码:
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#define N 1010
using namespace std;
int n,m,size,num,a[N*N],l[N],r[N],b[N*N],x,y,w,sy[N*N],lz[N];
char c;
inline char nc(){
static char ch[100010],*p1=ch,*p2=ch;
return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &a){
static char c=nc();int f=1;
for (;!isdigit(c);c=nc()) if (c=='-') f=-1;
for (a=0;isdigit(c);a=a*10+c-'0',c=nc());
a*=f;return;
}
inline void rebuild(int x){
for (int i=l[x]; i<=r[x]; ++i) b[i]=a[i];
return sort(b+l[x],b+r[x]+1);
}
inline void change(int x,int y,int w){
if (sy[x]==sy[y]){
for (int i=x; i<=y; ++i) a[i]+=w;
return rebuild(sy[x]);
}
for (int i=sy[x]+1; i<=sy[y]-1; ++i) lz[i]+=w;
for (int i=x; i<=r[sy[x]]; ++i) a[i]+=w;rebuild(sy[x]);
for (int i=l[sy[y]]; i<=y; ++i) a[i]+=w;rebuild(sy[y]);
return;
}
inline int find(int x,int y,int w){
int l=x,r=y,ans=y+1,mid;
while (l<=r){
mid=(l+r)>>1;
if (b[mid]<w) l=mid+1;
else ans=mid,r=mid-1;
}
return y-ans+1;
}
inline int query(int x,int y,int w){
int ans=0;
if (sy[x]==sy[y]){
for (int i=x; i<=y; ++i) if (a[i]>=w) ++ans;
return ans;
}
for (int i=sy[x]+1; i<=sy[y]-1; ++i) ans+=find(l[i],r[i],w-lz[i]);
for (int i=x; i<=r[sy[x]]; ++i) if (a[i]>=w) ++ans;
for (int i=l[sy[y]]; i<=y; ++i) if (a[i]>=w) ++ans;
return ans;
}
int main(void){
read(num),read(m),size=sqrt(num),n=(num-1)/size+1;
for (int i=1; i<=num; ++i){
read(a[i]),b[i]=a[i],sy[i]=(i-1)/size+1;
if (i%size==1) l[sy[i]]=i;
if (i%size==0) r[sy[i]]=i;
}
if (!r[n]) r[n]=num;
for (int i=1; i<=n; ++i) sort(b+l[i],b+r[i]+1);
while (m--){
c=nc();while (c!='M'&&c!='A') c=nc();
read(x),read(y),read(w);
switch (c){
case 'M': change(x,y,w); break;
case 'A': printf("%d\n",query(x,y,w)); break;
}
}
return 0;
}