I just started to learn the line segment tree, take this question as an example again, and make some notes
Question meaning: The question has two operations, one is to ask the sum of the [l,r] interval, and the other is to add C to each digit in the [l,r] interval
Analysis: Obviously, it is time-consuming and inefficient to directly add the number C to each digit in the interval, so we have to find another way, which is the lazy operation.
The lazy operation means that we do not add C to the numbers in the [l,r] interval first, that is, we do not directly add C to each number of the root of the tree, but push the mark +C to its two children. On the node, and update the child node sum[rt<<1]+=(tree[rt<<1].r-tree[rt<<1].l+1)*C (same for the right node), add [rt<<1]+=add[rt], add[rt]=0; in this way, only when this interval is used, will it use the sub-interval of this interval to update its own interval sum, Greatly improved efficiency
//pushdown void pushdown(int rt){ if(add[rt]){ add[rt<<1]+=add[rt]; add[rt<<1|1]+=add[rt]; sum[rt<<1]+=1LL*(tree[rt<<1].r-tree[rt<<1].l+1)*add[rt]; sum[rt<<1|1]+=1LL*(tree[rt<<1|1].r-tree[rt<<1|1].l+1)*add[rt]; add[rt]=0; } }
Because of the lazy operation, the node information will only be updated when this node is used. Therefore, when querying, the pushdown function must be used to push down the mark.
Below is the personal code
#define debug #include<stdio.h> #include<math.h> #include<cmath> #include<queue> #include<stack> #include<string> #include<cstring> #include<string.h> #include<algorithm> #include<iostream> #include<vector> #include<functional> #include<iomanip> #include<map> #include<set> #define pb push_back #define dbg(x) cout<<#x<<" = "<<(x)<<endl; using namespace std; typedef long long ll; typedef pair<int,int> pii; typedef pair<ll,ll>PLL; typedef pair<int,ll>Pil; const ll INF = 0x3f3f3f3f; const double inf=1e8+100; const double eps=1e-8; const int maxn =1e6; const int N = 510; const ll mod=1e9+7; //------ //define struct node{ int l, r; }tree[maxn<<2]; ll sum[maxn<<2],add[maxn<<2]; //pushup void pushup(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } //pushdown void pushdown(int rt){ if(add[rt]){ add[rt<<1]+=add[rt]; add[rt<<1|1]+=add[rt]; sum[rt<<1]+=1LL*(tree[rt<<1].r-tree[rt<<1].l+1)*add[rt]; sum[rt<<1|1]+=1LL*(tree[rt<<1|1].r-tree[rt<<1|1].l+1)*add[rt]; add[rt]=0; } } //buildtree void build(int l,int r,int rt) { tree[rt].l=l; tree[rt].r=r; add[rt]=0; if(l==r) { //gra[rt]=a[l]; scanf("%lld",&sum[rt]); return; } int m=l+r>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); pushup(rt); } //update void update(int L,int R,int C,int rt){ if(tree[rt].l==L&&tree[rt].r==R){ add[rt]+=C; sum[rt]+=1ll*C*(R-L+1); return; } if(tree[rt].l==tree[rt].r)return; pushdown(rt); int m=tree[rt].l+tree[rt].r>>1; if(R<=m){ update(L,R,C,rt<<1); }else if(L>m){ update(L,R,C,rt<<1|1); }else{ update(L,m,C,rt<<1); update(m+1,R,C,rt<<1|1); } pushup(rt); } //query ll query(int L,int R,int rt) { if(L==tree[rt].l&&R==tree[rt].r){ return sum[rt]; } pushdown(rt); ll ans=0; int m=tree[rt].l+tree[rt].r>>1; if(R<=m){ ans+=query(L,R,rt<<1); }else if(L>m){ ans+=query(L,R,rt<<1|1); }else{ ans+=query(L,m,rt<<1); ans+=query(m+1,R,rt<<1|1); } return ans; } //solve void solve() { int n,t; while(~scanf("%d%d",&n,&t)){ build(1,n,1); while(t--){ char mark[2]; int A,B,C; scanf("%s",&mark); if(mark[0]=='Q'){ scanf("%d%d",&A,&B); printf("%lld\n",query(A,B,1)); }else{ scanf("%d%d%d",&A,&B,&C); update(A,B,C,1); } } } } //main int main() { // ios_base::sync_with_stdio(false); #ifdef debug freopen("in.txt", "r", stdin); // freopen("out.txt","w",stdout); #endif // cin.tie(0); // cout.tie(0); solve(); /* #ifdef debug fclose(stdin); fclose(stdout); system("out.txt"); #endif */ return 0; }