### 線段樹模板整理

線段樹算是一種較為簡單的中級數據結構了，線段樹本身其實還是很簡單的，就是一棵二叉樹，每一個節點維護一塊區間的信息，如果根節點是$[1,n]$，那么左兒子就是$[1,n/2]$,右兒子就是$[n/2+1,n]$，如此二分下去就是一棵線段樹了，查找的時間復雜度是 $O\left ( \log_{2} N\right )$的，有圖為證：(網上找的)

#include <cstdio>
#include <algorithm>
using namespace std;

typedef long long LL;
static const int maxm=1e6+10;
LL tree[maxm],lazy[maxm],A[maxm],left[maxm],right[maxm];
int n,m;

void build(int num,int l,int r){
left[num]=l;right[num]=r;
int mid=(l+r)>>1;
if(l==r){ tree[num]=A[l]; return; }
build(num<<1,l,mid);
build(num<<1|1,mid+1,r);
tree[num]=tree[num<<1]+tree[num<<1|1];
}

void pushdown(int num){
if(lazy[num]){
int mid=(left[num]+right[num])>>1;
tree[num<<1]+=(mid-left[num]+1)*lazy[num];
tree[num<<1|1]+=(right[num]-mid)*lazy[num];
lazy[num<<1]+=lazy[num];
lazy[num<<1|1]+=lazy[num];
lazy[num]=0;
}
}

void update(int num,int l,int r,LL add){
if(left[num]>=l&&right[num]<=r){
tree[num]+=(right[num]-left[num]+1)*add;
lazy[num]+=add;
return;
}
if(left[num]>r||right[num]<l)return;
pushdown(num);
update(num<<1,l,r,add);
update(num<<1|1,l,r,add);
tree[num]=tree[num<<1]+tree[num<<1|1];
}

LL Query(int num,int l,int r){
if(left[num]>=l&&right[num]<=r)return tree[num];
if(left[num]>r||right[num]<l) return 0;
LL ret=0;
pushdown(num);
ret+=Query(num<<1,l,r);
ret+=Query(num<<1|1,l,r);
return ret;
}

int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%lld",&A[i]);
build(1,1,n);
for(int i=1;i<=m;i++){
int f,x,y;LL add;
scanf("%d",&f);
switch(f){
case 1:scanf("%d%d%lld",&x,&y,&add);update(1,x,y,add);break;
case 2:scanf("%d%d",&x,&y);printf("%lld\n",Query(1,x,y));break;
default:printf("Orz %%%");break;
}
}

return 0;
}
View Code

 1 #include <cstdio>
2
3 typedef long long LL;
4
5 static const int maxm=100005;
6
7 LL A[maxm],pls[maxm<<2],mul[maxm<<2],tr[maxm<<2];
8 int left[maxm<<2],right[maxm<<2];
9 int n,m;
10 LL MOD;
11
12 int build(int id,int l,int r){
13     left[id]=l;right[id]=r;mul[id]=1;
14     if(l==r)return tr[id]=A[l]%MOD,0;
15     int mid=(l+r)>>1;
16     build(id<<1,l,mid);
17     build(id<<1|1,mid+1,r);
18     tr[id]=(tr[id<<1]+tr[id<<1|1])%MOD;
19 }
20
21 void pushdown(int id){
22     int l=left[id];int r=right[id];int mid=(l+r)>>1;
23     pls[id<<1]=(pls[id<<1]*mul[id]%MOD+pls[id])%MOD;
24     pls[id<<1|1]=(pls[id<<1|1]*mul[id]%MOD+pls[id])%MOD;
25     mul[id<<1]=(mul[id]*mul[id<<1])%MOD;
26     mul[id<<1|1]=(mul[id]*mul[id<<1|1])%MOD;
27     tr[id<<1]=(tr[id<<1]*mul[id]%MOD+pls[id]*(mid-l+1)%MOD)%MOD;
28     tr[id<<1|1]=(tr[id<<1|1]*mul[id]%MOD+pls[id]*(r-mid)%MOD)%MOD;
29     mul[id]=1;pls[id]=0;
30 }
31
32 void modify(int id,int l,int r,int c,int opt){
33     if(left[id]>=l&&right[id]<=r){
34         if(opt==1){
35             mul[id]=(mul[id]*c)%MOD;
36             pls[id]=(pls[id]*c)%MOD;
37             tr[id]=(tr[id]*c)%MOD;
38         }else if(opt==2){
39             pls[id]=(pls[id]+c)%MOD;
40             tr[id]=(tr[id]+(LL)c*(right[id]-left[id]+1)%MOD)%MOD;
41         }
42         return ;
43     }
44     if(right[id]<l||left[id]>r)return ;
45     pushdown(id);
46     modify(id<<1,l,r,c,opt);
47     modify(id<<1|1,l,r,c,opt);
48     tr[id]=(tr[id<<1]+tr[id<<1|1])%MOD;
49 }
50
51 LL Query(int id,int l,int r){
52     if(left[id]>=l&&right[id]<=r)return tr[id]%MOD;
53     if(left[id]>r||right[id]<l)return 0;
54     pushdown(id);
55     return (Query(id<<1,l,r)%MOD+Query(id<<1|1,l,r)%MOD)%MOD;
56 }
57
58 int main(){
59     int opt,l,r,c;
60     scanf("%d%lld",&n,&MOD);
61     for(int i=1;i<=n;i++)scanf("%lld",&A[i]);
62     scanf("%d",&m);
63
64     build(1,1,n);
65
66     while(m--){
67         scanf("%d",&opt);
68         if(opt!=3){
69             scanf("%d%d%d",&l,&r,&c);
70             modify(1,l,r,c,opt);
71         }
72         else scanf("%d%d",&l,&r),printf("%lld\n",Query(1,l,r)%MOD);
73     }
74
75     return 0;
76 }
View Code

#### 注意！

© 2014-2020 ITdaan.com