不要当线段树都不会敲的菜鸡了。
线段树所要提供的是查询一个区间 内的信息,并允许修改操作。
节点数据向上更新
对于区间求和:
void push_up(int rt){ tree[rt] = tree[rt<<1] + tree[rt<<1|1]; }
对于区间求最值:
void push_up(int rt){ tree[rt] = max(tree[rt<<1],tree[rt<<1|1]); }
节点懒惰标记向下传递
对于区间求和:
void push_down(int rt,int len){ tree[rt<<1] += lazy[rt]*( len-(len>>1) ); lazy[rt<<1] += lazy[rt]; tree[rt<<1|1] += lazy[rt]*(len>>1); lazy[rt<<1|1] += lazy[rt]; lazy[rt]=0; }
对于区间求最值:
void push_down(int rt){ tree[rt<<1] += lazy[rt]; lazy[rt<<1] += lazy[rt]; tree[rt<<1|1] += lazy[rt]; lazy[rt<<1|1] += lazy[rt]; lazy[rt] = 0; }
建树
void build(int l,int r,int rt){ lazy[rt] = 0; if(l==r){ tree[rt] = 0; } int m = l+r>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); push_up(rt); }
更新:
void update(int ql,int qr,int l,int r,int rt,int val){ if(ql<=l && qr>=r){ tree[rt] += val*(r-l+1); lazy[rt] += val; return; } if(lazy[rt]) push_down(rt,r-l+1); int m = l+r>>1; if(ql<=m) update(ql,qr,l,m,rt<<1,val); if(qr>m) update(ql,qr,m+1,r,rt<<1|1,val); push_up(rt); }
查询:
ll query(int ql,int qr,int l,int r,int rt){ if(ql<=l && qr>=r) return tree[rt]; if(lazy[rt]) push_down(rt,r-l+1); int m = l+r>>1; int res=0; if(ql<=m) res += query(ql,qr,l,m,rt<<1); if(qr>m) res += query(ql,qr,m+1,r,rt<<1|1); return res; }