线段树
题目1:(带懒标记的线段树)
给定一个长度为 <span id="MathJax-Span-2" class="mrow"><span id="MathJax-Span-3" class="mi">NN 的数列 <span id="MathJax-Span-5" class="mrow"><span id="MathJax-Span-6" class="mi">AA,以及 <span id="MathJax-Span-8" class="mrow"><span id="MathJax-Span-9" class="mi">MM 条指令,每条指令可能是以下两种之一:
C l r d,表示把 <span id="MathJax-Span-11" class="mrow"><span id="MathJax-Span-12" class="mi">A<span id="MathJax-Span-13" class="mo">[<span id="MathJax-Span-14" class="mi">l<span id="MathJax-Span-15" class="mo">]<span id="MathJax-Span-16" class="mo">,<span id="MathJax-Span-17" class="mi">A<span id="MathJax-Span-18" class="mo">[<span id="MathJax-Span-19" class="mi">l<span id="MathJax-Span-20" class="mo">+<span id="MathJax-Span-21" class="mn">1<span id="MathJax-Span-22" class="mo">]<span id="MathJax-Span-23" class="mo">,<span id="MathJax-Span-24" class="mo">…<span id="MathJax-Span-25" class="mo">,<span id="MathJax-Span-26" class="mi">A<span id="MathJax-Span-27" class="mo">[<span id="MathJax-Span-28" class="mi">r<span id="MathJax-Span-29" class="mo">]A[l],A[l+1],…,A[r] 都加上 <span id="MathJax-Span-31" class="mrow"><span id="MathJax-Span-32" class="mi">dd。Q l r,表示询问数列中第 <span id="MathJax-Span-34" class="mrow"><span id="MathJax-Span-35" class="mi">l<span id="MathJax-Span-36" class="mo">∼<span id="MathJax-Span-37" class="mi">rl∼r 个数的和。
对于每个询问,输出一个整数表示答案。
题目来源:https://www.acwing.com/problem/content/244/
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 1e5+1;
int n,m,w[N];
struct node{
int l,r;
LL sum,add;
}tr[4*N];
void pushup(int u){
tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
}
void build(int u,int l,int r){
if(l==r)
tr[u]={l,r,w[l],0};
else{
tr[u]={l,r};
int mid = l + r>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
pushup(u);
}
}
void pushdown(int u){
if(tr[u].add){
node &left=tr[u<<1],&right=tr[u<<1|1];
tr[u<<1].add+=tr[u].add,left.sum+=(LL)(left.r-left.l+1)*tr[u].add;
tr[u<<1|1].add+=tr[u].add,right.sum+=(LL)(right.r-right.l+1)*tr[u].add;
tr[u].add=0;
}
}
void modify(int u,int l,int r,int d){
if(tr[u].l>= l and tr[u].r<=r){
tr[u].sum+=(LL)(tr[u].r-tr[u].l+1)*d;
tr[u].add+=d;
}
else{
int mid = tr[u].l +tr[u].r>>1;
pushdown(u);//为保证下面pushup正确更新区间,需要下传懒标记
if(l<=mid)modify(u<<1,l,r,d);
if(r>mid)modify(u<<1|1,l,r,d);
pushup(u);//只有区间被不完全覆盖才需要pushup比如1-10,其中1-5不操作,5-10加20
}//因为若完全覆盖则在pushdown时就可以更新整个子区间并下传标记
}
LL query(int u,int l,int r){
if(tr[u].l>= l and tr[u].r<=r)return tr[u].sum;
int mid=tr[u].l + tr[u].r >> 1;
LL sum=0;
pushdown(u);
if(l
if(tr[u].l>= l and tr[u].r<=r){
tr[u].sum+=(LL)(tr[u].r-tr[u].l+1)*d;
tr[u].add+=d;
}
else{
int mid = tr[u].l +tr[u].r>>1;
pushdown(u);//为保证下面pushup正确更新区间,需要下传懒标记
if(l<=mid)modify(u<<1,l,r,d);
if(r>mid)modify(u<<1|1,l,r,d);
pushup(u);//只有区间被不完全覆盖才需要pushup比如1-10,其中1-5不操作,5-10加20
}//因为若完全覆盖则在pushdown时就可以更新整个子区间并下传标记
}
LL query(int u,int l,int r){
if(tr[u].l>= l and tr[u].r<=r)return tr[u].sum;
int mid=tr[u].l + tr[u].r >> 1;
LL sum=0;
pushdown(u);
if(l
