整理了个新的线段树的模板,暑期集训的时候学长给的模板,每个节点单单存了自己所要维护的内容,还是少了点。导致在写pushdown的时候,len我会有点难写。所以就整理个新的模板。
每个节点还存了l,r,lazy,len,写起来思路清晰多了。
#include<iostream> #include<cstdio> #define lson (rt << 1) #define rson (rt << 1 | 1) #define Lson lson, l, mid #define Rson rson, mid + 1, r typedef long long ll; const int INF=0x3f3f3f3f; const int maxn=1e5+7; using namespace std; struct node { ll val;//值 int len;//长度 ll lazy;//标记 int l,r;//左右端点 }tree[maxn<<2]; ll arr[maxn]; int n,m; void build(int rt,int l,int r) //建树 { tree[rt].lazy=0; tree[rt].l=l;tree[rt].r=r; tree[rt].len=r-l+1; if (l==r) tree[rt].val=arr[l];//到达树端点,给val赋值 else { int mid=(l+r)/2; build(Lson); build(Rson); tree[rt].val=tree[lson].val+tree[rson].val; } } void pushdown(int rt) //向下传递lazy标记 { if (tree[rt].lazy) { tree[lson].lazy+=tree[rt].lazy; tree[rson].lazy+=tree[rt].lazy; tree[lson].val+=tree[lson].len*tree[rt].lazy; tree[rson].val+=tree[rson].len*tree[rt].lazy; tree[rt].lazy=0; } } void add(int rt,int id,ll addval) //单点更新 { if (tree[rt].l==tree[rt].r) { tree[rt].val+=addval; return; } else { int mid=(tree[rt].l+tree[rt].r)/2; if (id<=mid) add(lson,id,addval); else add(rson,id,addval); tree[rt].val=tree[lson].val+tree[rson].val; } } ll query(int rt,int l,int r) //计算区间和 { if (tree[rt].l>=l&&tree[rt].r<=r) return tree[rt].val; if (tree[rt].l>r||tree[rt].r<l) return 0; pushdown(rt); return query(lson,l,r)+query(rson,l,r); } void update(int rt,int l,int r,ll addval) //区间更新 { ll mid; if (tree[rt].l>=l&&tree[rt].r<=r) { tree[rt].lazy+=addval; tree[rt].val+=tree[rt].len*addval; return; } if (tree[rt].l>r||tree[rt].r<l) return; pushdown(rt); update(lson,l,r,addval); update(rson,l,r,addval); tree[rt].val=tree[lson].val+tree[rson].val; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { scanf("%lld",&arr[i]); } build(1,1,n); for (int i=1;i<=m;i++) { char s[10]; scanf("%s",s); int l,r; ll x; if (s[0]=='C') { scanf("%d%d%lld",&l,&r,&x); update(1,l,r,x); } else { scanf("%d%d",&l,&r); printf("%lld ",query(1,l,r)); } } return 0; }