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

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];
}

 

你可能感兴趣的:(数据结构)