1. 程式人生 > 實用技巧 >線段樹_[模板]

線段樹_[模板]

題目:洛谷P3372 【模板】線段樹 1

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdio> 
using namespace std;
int n,m;
long long a[100005];
long long tree[10000005];
int d[10000005][3];
long long lazy[10000005];
void buildtree(int root,int s,int t)
{
    if (s==t)
     {
         tree[root]=a[s];
        d[root][
1]=s; d[root][2]=t; return; } buildtree(root*2,s,(s+t)/2); buildtree(root*2+1,(s+t)/2+1,t); tree[root]=tree[root*2]+tree[root*2+1]; d[root][1]=s; d[root][2]=t; } void down(int root) { if(lazy[root]!=0) { tree[root*2]+=(d[root*2][2]-d[root*2][1]+1)*lazy[root]; tree[root
*2+1]+=(d[root*2+1][2]-d[root*2+1][1]+1)*lazy[root]; lazy[root*2]+=lazy[root]; lazy[root*2+1]+=lazy[root]; lazy[root]=0; } } void change(int root,int s,int t,int l,int r,int add) { if (t<l || s>r) return; if (l<=s && r>=t) { tree[root]
+=(d[root][2]-d[root][1]+1)*add; lazy[root]+=add; return; } down(root); int mid=(s+t)/2; change(root*2,s,mid,l,r,add); change(root*2+1,mid+1,t,l,r,add); tree[root]=tree[root*2]+tree[root*2+1]; } long long find(int root,int s,int t,int l,int r) { if (t<l || s>r) return 0; if (l<=s && r>=t) { return (tree[root]); } down(root); return (find(root*2,s,(s+t)/2,l,min(r,(s+t)/2))+find(root*2+1,(s+t)/2+1,t,max(l,(s+t)/2+1),r)); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); buildtree(1,1,n); for(int i=1;i<=m;i++) { long long k,a,b,c; scanf("%lld",&k); if (k==1) { scanf("%lld%lld%lld",&a,&b,&c); change(1,1,n,a,b,c); } if (k==2) { scanf("%lld%lld",&a,&b); printf("%lld\n",find(1,1,n,a,b)); } } }