【分块】【线段树】bzoj3212 Pku3468 A Simple Problem with Integers
线段树入门题……
因为poj原来的代码莫名RE,所以丧病地写了区间修改的分块……
其实就是块上打标记,没有上传下传之类。
1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 int n,m,a[100001],l[400],r[400],delta[400],num[100001],sum,sz,x,y,v; 5 char op[1]; 6 long long sumv[400]; 7 void makeblock() 8 { 9 sz=sqrt(n); 10 for(sum=1;sum*sz<n;sum++) 11 { 12 l[sum]=(sum-1)*sz+1; 13 r[sum]=sum*sz; 14 for(int i=l[sum];i<=r[sum];i++) {num[i]=sum; sumv[sum]+=a[i];} 15 } 16 l[sum]=sz*(sum-1)+1; r[sum]=n; 17 for(int i=l[sum];i<=r[sum];i++) {num[i]=sum; sumv[sum]+=a[i];} 18 } 19 inline void update() 20 { 21 if(num[x]+1>=num[y]){for(int i=x;i<=y;i++) a[i]+=v;} 22 else 23 { 24 for(int i=x;i<=r[num[x]];i++) a[i]+=v; 25 for(int i=l[num[y]];i<=y;i++) a[i]+=v; 26 for(int i=num[x]+1;i<num[y];i++) delta[i]+=v; 27 } 28 } 29 inline void query() 30 { 31 long long ans=0; 32 if(num[x]+1>=num[y]){for(int i=x;i<=y;i++) ans+=a[i];} 33 else 34 { 35 for(int i=x;i<=r[num[x]];i++) ans+=(long long)(delta[num[x]]+a[i]); 36 for(int i=l[num[y]];i<=y;i++) ans+=(long long)(delta[num[y]]+a[i]); 37 for(int i=num[x]+1;i<num[y];i++) ans+=sumv[i]+(long long)((l[i]-r[i]+1)*delta[i]); 38 } 39 printf("%lld\n",ans); 40 } 41 int main() 42 { 43 scanf("%d%d",&n,&m); 44 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 45 for(int i=1;i<=m;i++) 46 { 47 scanf("%s%d%d",op,&x,&y); 48 if(op[0]=='Q') query(); 49 else {scanf("%d",&v); update();} 50 } 51 return 0; 52 }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/