【分块】bzoj3343 教主的魔法
分块,每个块内部有序化,查询时二分。修改时直接修改覆盖在各个块上的delta。
块大小O(sqrt(n*log(n)))比较合适。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 using namespace std; 5 #define N 1000001 6 char op; int n,m,x,y,v,a[N],l[4500],r[4500],num[N],b[N],delta[4500]; 7 int Num,CH[12],f,c; 8 inline void R(int &x){ 9 c=0;f=1; 10 for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1; 11 for(x=0;c>='0'&&c<='9';c=getchar())(x*=10)+=(c-'0'); 12 x*=f; 13 } 14 inline void P(int x){ 15 if(x<10)putchar(x+'0'); 16 else{P(x/10);putchar(x%10+'0');} 17 } 18 void makeblock() 19 { 20 for(int i=1;i<=n;++i) b[i]=a[i]; 21 int sz=sqrt((double)n*log2(n)),sum=1; if(!sz) sz=1; 22 for(;sum*sz<n;++sum) 23 { 24 l[sum]=r[sum-1]+1; r[sum]=sum*sz; 25 for(int i=l[sum];i<=r[sum];++i) num[i]=sum; 26 sort(b+l[sum],b+r[sum]+1); 27 } 28 l[sum]=r[sum-1]+1; r[sum]=n; 29 for(int i=l[sum];i<=r[sum];++i) num[i]=sum; 30 sort(b+l[sum],b+r[sum]+1); 31 } 32 void work(const int &L,const int &R) 33 { 34 for(int i=L;i<=R;++i) a[i]+=v; 35 for(int i=l[num[L]];i<=r[num[L]];++i) b[i]=a[i]; 36 sort(b+l[num[L]],b+r[num[L]]+1); 37 } 38 inline void update() 39 { 40 if(num[x]==num[y]) work(x,y); 41 else 42 { 43 work(x,r[num[x]]); work(l[num[y]],y); 44 for(int i=num[x]+1;i<num[y];++i) delta[i]+=v; 45 } 46 } 47 inline void query() 48 { 49 int res=0; 50 if(num[x]==num[y]) {for(int i=x;i<=y;++i) if(a[i]+delta[num[x]]>=v) ++res;} 51 else 52 { 53 for(int i=x;i<=r[num[x]];++i) if(a[i]+delta[num[x]]>=v) ++res; 54 for(int i=l[num[y]];i<=y;++i) if(a[i]+delta[num[y]]>=v) ++res; 55 for(int i=num[x]+1;i<num[y];++i) 56 res+=(b+r[i]-lower_bound(b+l[i],b+r[i]+1,v-delta[i])+1); 57 } P(res); puts(""); 58 } 59 int main() 60 { 61 R(n); R(m); for(int i=1;i<=n;++i) R(a[i]); makeblock(); 62 for(int i=1;i<=m;++i) 63 { 64 getchar(); op=getchar(); R(x); R(y); R(v); 65 if(op=='M') update(); else query(); 66 } 67 return 0; 68 }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/