线段树模版(区间延迟更新)

///区间求和
const int maxn=100000;
int N,Q;                // N为区间右端点(即数的个数),Q为查询次数
long long m;
struct xx{
    long long sum,inf;    //inf,延迟更新,当需要更新时才更新,否则存放入 inf
}tree[4*maxn+10];                    //一般都开4倍
void build(int l,int r,int root){    //建树  调用为   build(1,N,1);
    tree[root].inf=0;
    if(l==r){
        scanf("%lld",&m);
        tree[root].sum=m;
    } else {
        int mid=(l+r)/2;
        build(l,mid,root*2);
        build(mid+1,r,root*2+1);
        tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;
    }
}
void pushdown(int l,int r,int root){                        //向下更新
    int mid=(l+r)/2;
    tree[root*2].inf+=tree[root].inf;                       //注意,  有的题中 是替换的意思, 则 直接 = 就行,不用  += (以下的  +=  符号也一样)
    tree[root*2+1].inf+=tree[root].inf;
    tree[root*2].sum+=(mid-l+1)*tree[root].inf;
    tree[root*2+1].sum+=(r-(mid+1)+1)*tree[root].inf;
    tree[root].inf=0;
    return ;
}
void update(int l,int r,int ul,int ur,int add,int root){    //更新区间, ul,ur为需要更新的区间
    if(ul<=l&&r<=ur){
        tree[root].sum+=(r-l+1)*add;
        tree[root].inf+=add;
    } else {
        if(tree[root].inf!=0) pushdown(l,r,root);
        int mid=(l+r)/2;
        if(ul<=mid) update(l,mid,ul,ur,add,root*2);
        if(ur>mid) update(mid+1,r,ul,ur,add,root*2+1);
        tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;
    }
}
long long query(int l,int r,int ql,int qr,int root){            //查询, ql qr 为查询的区间
    if(ql<=l&&r<=qr)
        return tree[root].sum;
    else {
        if(tree[root].inf!=0) pushdown(l,r,root);
        int mid=(l+r)/2;
        long long ans=0;
        if(ql<=mid) ans+=query(l,mid,ql,qr,root*2);
        if(qr>mid) ans+=query(mid+1,r,ql,qr,root*2+1);
        return ans;
    }
}

猜你喜欢

转载自blog.csdn.net/no_o_ac/article/details/81182211