树状数组简单模板

1:单点修改:

void update(int x,int v)//单点修改(x节点加上v)
{
    for(int i=x;i<=n;i+=lowbit(i))
        c[i]+=v;
}

2:前缀和:

int sum(int x)//sum[1,x]
{
    int ans=0;
    for(int i=x;i>=1;i-=lowbit(i))
        ans+=c[i];
    return ans;
}

3:区间修改,单点求值(差分思想)

int solve(int l,int r,int v,int x)//[l,r]区间同时加上v,同时求x节点值(这时转化为求前缀和)
{
    c[l]+=v;
    c[r+1]-=v;
    return sum(x);
}

4:区间修改,区间求和(差分思想,辅助数组)

int solve(int l,int r,int v)//[l,r]同时增加v,同时求得[l,r]区间和
{
    for(int i=1;i<=n;i++){
        cin>>a[i];
        update(diff,i,a[i]-a[i-1]);
        update(aux,i,(i-1)*(a[i]-a[i-1]));
    }
    l--;
    int sumr=r*sum(diff,r)-sum(aux,r);
    int suml=l*sum(diff,l)-sum(aux,l);
    return sumr-suml;
}

5:区间最大最小值

void update(int x)//更改节点值
{
    for(int i=x;i<=n;i+=lowbit(i)){//将所有x能影响到的节点更新
        h[i]=a[i];//首先取原数组值
        for(int j=1;j<lowbit(i);j<<=1){//在子节点中寻求最优值
            h[i]=max(h[i],h[i-j]);
        }
    }
}
int querymax(int l,int r)//区间最大值
{
    int ans=0;
    while(r>=l){
        for(;r-lowbit(r)>=l;r-=lowbit(r))//找到该节点所示的区间包含于[x,y],可直接取根节点最优值
            ans=max(ans,h[r]);
        ans=max(ans,a[r]);//取当前区间右端点,下一步进行[x,y-1]区间寻找
        r--;
    }
    return ans;
}

猜你喜欢

转载自www.cnblogs.com/cherish-lin/p/10957984.html