功能 在区间上进行信息统计,需注意信息在节点之间传递的属性是什么,根据属性的不同来改变写法 简写 #define ul u * 2 #define ur u * 2 + 1 #define l(u) tr[u].l #define r(u) tr[u].r #define dat(u) tr[u].dat #define lay(u) tr[u].delay 存储( 下标从 1 开始 ) struct node { int l, r; //当前节点的左右区间 int delay; //延迟标记( 只有涉及区间修改时才需 ) int dat; //信息1 }tr[N * 4]; //节点个数的四倍大小 递归后上捞节点信息( 创建 修改 ) void pushup( int u ) //两个子节点递归完成后更新父节点 { tr[u].dat = tr[u * 2].dat + tr[u * 2 + 1].dat; } 递归前下传延迟标记( 区间修改 查询 ) void pushdown( int u ) { //左右子节点分别加上父节点的延迟标记 tr[u * 2].delay += tr[u].delay; //和延迟标记对区间所带来的影响 tr[u * 2].dat += ( tr[u * 2].r - tr[u * 2].l + 1) * tr[u].delay; tr[u * 2 + 1].delay += tr[u].delay; tr[u * 2 + 1].dat += ( tr[u * 2 + 1].r - tr[u * 2 + 1].l + 1) * tr[u].delay; tr[u].delay = 0; //节点的延迟标记清零 } 创建 void build( int u, int l, int r ) //当前正在创建区间为[l ~ r]的第u个节点 { tr[u] = { l, r }; //表明节点的左右区间 tr[u].delay = 0; //和延迟标记 if( l == r ) tr[u].dat = a[l]; //如果是叶子节点则填充信息 else { //如果不是叶子节点则递归左右节点 int mid = l + r >> 1; //拆分 build( u * 2, l, mid ); //递归左子节点 build( u * 2 + 1, mid + 1, r ); //递归右子节点 pushup( u ); //上捞节点信息 } } 单点修改 int modify( int u, int x, int y ) //把编号为 x 的数修改为 y { if( tr[u].l == x && tr[u].r == x ) //如果是叶子节点则修改信息 tr[u].dat = y; else //如果不是叶子节点则递归左右节点 { int mid = tr[u].l + tr[u].r >> 1; //拆分 if( x <= mid ) modify( u * 2, x, y ); //递归左子节点 else modify( u * 2 + 1, x, y ); //递归右子节点 pushup( u ); //上捞节点信息 } } 区间修改 void modify(int u, int l, int r, int d) //给区间 [l ~ r] 施加影响 d { if ( l <= tr[u].l && tr[u].r <= r) //如果完全覆盖 { tr[u].dat += ( tr[u].r - tr[u].l + 1 ) * d;//更新节点信息 tr[u].delay += d; //给节点打延迟标记 } else //如果不完全覆盖 { pushdown( u ); //下传延迟标记 int mid = tr[u].l + tr[u].r >> 1; //拆分 if ( l <= mid ) modify( u * 2, l, r, d ); //递归左子节点 if ( mid < r ) modify( u * 2 + 1, l, r, d ); //递归右子节点 pushup( u ); //上捞节点信息 } } 查询 int query( int u, int l, int r ) //l r 相同则为查询点 { if( l <= tr[u].l && tr[u].r <= r ) //如果完全覆盖 return tr[u].dat; //返回查询结果备用 int res = 0; //定义查询初值 pushdown( u ); //下传延迟标记 int mid = tr[u].l + tr[u].r >> 1; //拆分 if( l <= mid ) res = ...query( u * 2, l, r ); //递归查询左子节点 if( mid < r ) res = ...query(u * 2 + 1, l, r ); //递归查询右子节点 return res; //返回查询结果 }