线段树模板

来源:互联网 发布:英语流利说 知乎 编辑:程序博客网 时间:2024/06/05 01:11
#define maxn 100007  //元素总个数#define ls l,m,rt<<1#define rs m+1,r,rt<<1|1int Sum[maxn<<2],Add[maxn<<2];//Sum求和,Add为懒惰标记int A[maxn],n;//存原数组数据下标[1,n]///建树:Build(1,n,1);//PushUp函数更新节点信息 ,这里是求和void PushUp(int rt){Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1];}//Build函数建树void Build(int l,int r,int rt){ //l,r表示当前节点区间,rt表示当前节点编号if(l==r) {//若到达叶节点Sum[rt]=A[l];//储存数组值return;}int m=(l+r)>>1;//左右递归Build(l,m,rt<<1);Build(m+1,r,rt<<1|1);//更新信息PushUp(rt);}///点修改,假设A[L]+=C: Update(L,C,1,n,1);void Update(int L,int C,int l,int r,int rt){//l,r表示当前节点区间,rt表示当前节点编号if(l==r){//到叶节点,修改Sum[rt]+=C;return;}int m=(l+r)>>1;//根据条件判断往左子树调用还是往右if(L <= m) Update(L,C,l,m,rt<<1);else       Update(L,C,m+1,r,rt<<1|1);PushUp(rt);//子节点更新了,所以本节点也需要更新信息}///区间修改,假设A[L,R]+=C: Update(L,R,C,1,n,1);void Update(int L,int R,int C,int l,int r,int rt){//L,R表示操作区间,l,r表示当前节点区间,rt表示当前节点编号if(L <= l && r <= R){//如果本区间完全在操作区间[L,R]以内Sum[rt]+=C*(r-l+1);//更新数字和,向上保持正确Add[rt]+=C;//增加Add标记,表示本区间的Sum正确,子区间的Sum仍需要根据Add的值来调整return ;}int m=(l+r)>>1;PushDown(rt,m-l+1,r-m);//下推标记//这里判断左右子树跟[L,R]有无交集,有交集才递归if(L <= m) Update(L,R,C,l,m,rt<<1);if(R >  m) Update(L,R,C,m+1,r,rt<<1|1);PushUp(rt);//更新本节点信息}///区间查询:询问A[L,R]的和///首先是下推标记的函数:void PushDown(int rt,int ln,int rn){//ln,rn为左子树,右子树的数字数量。if(Add[rt]){//下推标记Add[rt<<1]+=Add[rt];Add[rt<<1|1]+=Add[rt];//修改子节点的Sum使之与对应的Add相对应Sum[rt<<1]+=Add[rt]*ln;Sum[rt<<1|1]+=Add[rt]*rn;//清除本节点标记Add[rt]=0;}}///然后是区间查询的函数:int ANS=Query(L,R,1,n,1);int Query(int L,int R,int l,int r,int rt){//L,R表示操作区间,l,r表示当前节点区间,rt表示当前节点编号if(L <= l && r <= R){//在区间内,直接返回return Sum[rt];}int m=(l+r)>>1;//下推标记,否则Sum可能不正确PushDown(rt,m-l+1,r-m);//累计答案int ANS=0;if(L <= m) ANS+=Query(L,R,l,m,rt<<1);if(R >  m) ANS+=Query(L,R,m+1,r,rt<<1|1);return ANS;}



#include <iostream>#include <set>#include <map>#include <stack>#include <cmath>#include <queue>#include <cstdio>#include <bitset>#include <string>#include <vector>#include <iomanip>#include <cstring>#include <algorithm>#include <functional>#define PI acos(-1)#define eps 1e-8#define inf 0x3f3f3f3f#define debug(x) cout<<"---"<<x<<"---"<<endltypedef long long ll;using namespace std;#define maxn 200005  //元素总个数#define ls l,m,rt<<1#define rs m+1,r,rt<<1|1#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int NV = 100005;int sum[NV << 2], add[NV << 2];void PushUp(int rt){    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];}void PushDown(int rt, int m){    if (add[rt])    {        add[rt << 1] += add[rt];        add[rt << 1 | 1] += add[rt];        sum[rt << 1] += add[rt] * (m - (m >> 1));        sum[rt << 1 | 1] += add[rt] * (m >> 1);        add[rt] = 0;    }}void build(int l, int r, int rt = 1){    add[rt] = 0;    if (l == r)    {        sum[rt] = 0;        return ;    }    int m = (l + r) >> 1;    build(lson);    build(rson);    PushUp(rt);}void update1(int L, int c, int l, int r, int rt = 1){    if (L == l && l == r)    {        sum[rt] += c;        return ;    }    int m = (l + r) >> 1;    if (L <= m)    {        update1(L , c , lson);    }    else    {        update1(L , c , rson);    }    PushUp(rt);}void update2(int L, int R, int c, int l, int r, int rt = 1){    if (L <= l && r <= R)    {        add[rt] += c;        sum[rt] += c * (r - l + 1);        return ;    }    PushDown(rt , r - l + 1);    int m = (l + r) >> 1;    if (L <= m)    {        update2(L , R , c , lson);    }    if (m < R)    {        update2(L , R , c , rson);    }    PushUp(rt);}int query(int L, int R, int l, int r, int rt = 1){    if (L <= l && r <= R)    {        return sum[rt];    }    PushDown(rt , r - l + 1);    int m = (l + r) >> 1;    int ret = 0;    if (L <= m)    {        ret += query(L , R , lson);    }    if (m < R)    {        ret += query(L , R , rson);    }    return ret;}


原创粉丝点击