【分块】【线段树】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
",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 }
原文地址:https://www.cnblogs.com/autsky-jadek/p/4031363.html