P2801 教主的魔法(分块入门)
两个月之前听yyr学长讲的分块,感觉是个很神奇的暴力,但到现在还是懵的一匹
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+7; int belong[maxn]; int a[maxn]; int b[maxn]; int d[maxn]; int l[maxn]; int r[maxn]; int p[maxn]; int n,q; int num,block; void build()//预处理块 { block=sqrt(n); num=n/block; if(n%block) { num++; } for(int i=1;i<=n;i++) { belong[i]=(i-1)/block+1; b[i]=a[i]; } for(int i=1;i<=num;i++) { l[i]=(i-1)*block+1; r[i]=i*block; } r[num]=n; for(int i=1;i<=num;i++) { sort(b+l[i],b+r[i]+1); } } void update(int ll,int rr,int w) { if(belong[ll]==belong[rr]) { for(int i=ll;i<=rr;i++) { a[i]+=w; } for(int i=l[belong[ll]];i<=r[belong[ll]];i++) { b[i]=a[i]; } sort(b+l[belong[ll]],b+r[belong[ll]]+1); } else { for(int i=ll;i<=r[belong[ll]];i++) { a[i]+=w; } for(int i=l[belong[ll]];i<=r[belong[ll]];i++) { b[i]=a[i]; } sort(b+l[belong[ll]],b+r[belong[ll]]+1); for(int i=l[belong[rr]];i<=rr;i++) { a[i]+=w; } for(int i=l[belong[rr]];i<=r[belong[rr]];i++) { b[i]=a[i]; } sort(b+l[belong[rr]],b+r[belong[rr]]+1); for(int i=belong[ll]+1;i<=belong[rr]-1;i++) { p[i]+=w; } } } int ask(int ll,int rr,int c) { int ans=0; if(belong[ll]==belong[rr]) { for(int i=ll;i<=rr;i++) { if(a[i]+p[belong[i]]>=c) { ans++; } } printf("%d\n",ans); } else { for(int i=ll;i<=r[belong[ll]];i++) { if(a[i]+p[belong[i]]>=c) { ans++; } } for(int i=l[belong[rr]];i<=rr;i++) { if(a[i]+p[belong[i]]>=c) { ans++; } } for(int i=belong[ll]+1;i<belong[rr];i++) { int l1=l[i],r1=r[i],result=0,mid; while(l1<=r1) { mid=(l1+r1)>>1; if(b[mid]+p[i]>=c) { r1=mid-1; result=r[i]-mid+1; } else { l1=mid+1; } } ans+=result; } printf("%d\n",ans); } } int main() { int A,B,C; char ch[5]; scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } build(); while(q--) { scanf("%s",ch); scanf("%d%d%d",&A,&B,&C); if(ch[0]=='A') { ask(A,B,C); } else { update(A,B,C); } } return 0; }