我向来不喜欢废话,直接开始说啦!
传送门:P3372 【模板】线段树 1
预处理:
①段数t=sqrt(n);
②每段左边界L[i]=(i-1)*t+1;
③每段右边界R[i]=i*t;
④补充处理:t2小于n的再补一段,左边界R[t-1]+1,右边界n;
⑤区间和sum[i]=∑jL[i]<=j<=R[i]a[j];
⑥预设增量标记add=0;
区间修改:
(情况一)l,r在同一块内:直接对区间内的每个数加,区间和用询问长度用修改1次;
(情况二)l,r不在同一块内:
①l+1到r-1块内:全部修改增量标记;
②l块:做法同情况1,右边界是R[pos[l]];
③r快:做法同情况1,左边界是L[pos[r]];
区间查询:
(情况一)l,r在同一块内:直接对区间内的数求和,再加上增量标记*询问长;
(情况二)l,r不在同一块内:
①l+1到r-1块内:全部加上区间和以及增量标记*段长;
②l块:做法同情况1,右边界是R[pos[l]];
③r快:做法同情况1,左边界是L[pos[r]];
整体思想:大段维护,菊(抱歉打错字啦)局部朴素
撒花!
真没了,回去吧
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 //Written By Peter0701 2 #include<bits/stdc++.h> 3 using namespace std; 4 int n,m,t,l,r,k,op; 5 int L[100005],R[100005],pos[100005]; 6 long long sum[100005],add[100005],a[100005]; 7 inline int read() 8 { 9 int ret=0,f=1; 10 char ch=getchar(); 11 while(ch>'9'||ch<'0') 12 { 13 if(ch=='-') f=-1; 14 ch=getchar(); 15 } 16 while(ch>='0'&&ch<='9') 17 { 18 ret=(ret<<1)+(ret<<3)+ch-'0'; 19 ch=getchar(); 20 } 21 return ret*f; 22 } 23 void change(int l,int r,int d) 24 { 25 int p=pos[l],q=pos[r]; 26 if(p==q) 27 { 28 for(register int i=l;i<=r;i++) 29 a[i]+=d; 30 sum[p]+=d*(r-l+1); 31 } 32 else 33 { 34 for(register int i=p+1;i<=q-1;i++) 35 add[i]+=d; 36 for(register int i=l;i<=R[p];i++) 37 a[i]+=d; 38 sum[p]+=d*(R[p]-l+1); 39 for(register int i=L[q];i<=r;i++) 40 a[i]+=d; 41 sum[q]+=d*(r-L[q]+1); 42 } 43 } 44 long long ask(int l,int r) 45 { 46 int p=pos[l],q=pos[r]; 47 long long ans=0; 48 if(p==q) 49 { 50 for(register int i=l;i<=r;i++) 51 ans+=a[i]; 52 ans+=add[p]*(r-l+1); 53 } 54 else 55 { 56 for(register int i=p+1;i<=q-1;i++) 57 ans+=sum[i]+add[i]*(R[i]-L[i]+1); 58 for(register int i=l;i<=R[p];i++) 59 ans+=a[i]; 60 ans+=add[p]*(R[p]-l+1); 61 for(register int i=L[q];i<=r;i++) 62 ans+=a[i]; 63 ans+=add[q]*(r-L[q]+1); 64 } 65 return ans; 66 } 67 int main() 68 { 69 n=read(); 70 m=read(); 71 for(register int i=1;i<=n;i++) 72 a[i]=read(); 73 t=sqrt(n); 74 for(register int i=1;i<=t;i++) 75 { 76 L[i]=(i-1)*t+1; 77 R[i]=i*t; 78 } 79 if(R[t]<n) 80 t++,L[t]=R[t-1]+1,R[t]=n; 81 for(register int i=1;i<=t;i++) 82 { 83 for(register int j=L[i];j<=R[i];j++) 84 { 85 pos[j]=i; 86 sum[i]+=a[j]; 87 } 88 } 89 while(m--) 90 { 91 op=read(); 92 l=read(); 93 r=read(); 94 if(op==1) 95 { 96 k=read(); 97 change(l,r,k); 98 } 99 else 100 { 101 printf("%lld\n",ask(l,r)); 102 } 103 } 104 return 0; 105 }