数据结构--树状数组总结

1.单点更新&前缀和查询(->区间查询)

int tr[maxn];//树状数组 
void add(int tr[],int x,int k)
{
    while(x < maxn){
        tr[x] += k;
        x += (x & -x);
    }
}
int query(int tr[],int x){
    int ans =0 ;
    while(x){
        ans += tr[x];
        x -= (x & -x);
    }
    return ans;
}

2.区间更新&区间查询

区间更新这里引进了一个数组delta数组,delta[i]表示区间 [i, n] 的共同增量,每次你需要更新的时候只需要更新delta数组就行了,因为每段区间更新的数都记录在这个数组中。

sum[i]=a[1]+a[2]+a[3]+......+a[i]+delta[1]*(i-0)+delta[2]*(i-1)+delta[3]*(i-2)+......+delta[i]*(i-i+1);    
 
          = sigma( a[x] ) + sigma( delta[x]  *  (i + 1 - x) )  
          = sigma( a[x] ) + (i + 1) * sigma( delta[x] ) - sigma( delta[x] * x ) 
ll A[maxn];//A[i]表示原数组
ll delta[maxn];//delta[i] 表示A[i,n]共同的增量
ll xdelta[maxn];//xdelta[i] = i * delta[i]

void add(int x,int key,ll arr[])
{
    while(x < maxn){
        arr[x] += key;
        x += (x & -x);
    }
}
ll query(int x,ll arr[])
{
    ll ans = 0;
    while (x) {
        ans += arr[x];
        x -= (x & -x);
    }
    return ans;
}

//step1:A数组记录初值
for (int i = 1; i <= n; i++) {
    scanf("%d",&t);
    update(i,t,A);
}
//step2:要在区间[a,b]加上c,需要更新delta和xdelta数组
if(op == 'C'){
    scanf("%d%d%d",&a,&b,&c);
    update(a, c, delta);
    update(b + 1, -c, delta);
    update(a, a * c, xdelta);
    update(b + 1, -c * (b + 1), xdelta);
}
//step3:区间查询[a,b],需要统计A,delta,xdelta数组
if(op == 'Q'){
    scanf("%d%d",&a,&b);
    ans1 = sum(b, A) + (b + 1) * sum(b, delta) - sum(b, xdelta);
    if(a > 1) ans2 = sum(a - 1, A) + a * sum(a - 1, delta) - sum(a - 1, xdelta);
    else ans2 = 0;
    printf("%lld\n",ans1 - ans2);
}

3.区间更新&单点查询

如果查询时仅需要单点查询,那么可以使用差分。

ans[x] = A[x] + delta[x] + delta[x - 1] + ... + delta[1]   //delta数组的前缀和

            = A[x] + query(delta,x)

ll A[maxn];//A表示原数组
ll delta[maxn];//delta[i]表示[i,n]的共同增量

void add(ll tr[],int x,ll k){
    while(x < maxn) {
        tr[x] += k;
        x += (x & -x);
    }
}
ll query(ll tr[],int x){
    ll ans = 0;
    while(x){
        ans += tr[x];
        x -= (x & -x);
    }
    return ans;
}

//区间更新,在区间[a,b]加上c
if(op == 'C'){
    add(delta,a,c);
    add(delta,b + 1,-c);
}
//单点查询,查询x的值
if(op == 'Q'){
    ll ans = query(delta,x) + A[x];
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值