の拡張フェンウィックツリー

まず、基本的なフェンウィックツリー

(A)接頭辞と実装(修飾の単一のポイントを、クエリ間隔)

inline int lowbit(int x){return x&-x;}
inline void change(int x,int k){
    while(x<=n){
        tree[x]+=k;
        x+=lowbit(x);
    }
}
inline ll query(int x){
    ll ans=0;
    while(x){
        ans+=tree[x];
        x-=lowbit(x);
    }
    return ans;
}

(B)は、差動実装(セクションが問い合わせの単一の点を変更し)

修飾に差を維持するために、間隔、問い合わせの単一の点を変更

change(x,k);
change(y+1,-k);

第二に、フェンウィックツリーの範囲(ゾーンの変更、レンジクエリ)

検討\([1、R] \ ) 間隔と

\(ツリー[I] = [I] -a [I-1] \)、我们有\([I] = \ sum_ \ left.k = 1 \右^ Iツリー[K] \)


\ [\ sum_ \ left.i = 1 \右^ RA [I] = \ sum_ \ left.i = 1 \右^ R \ sum_ \ left.k = 1つの\右^ Iツリー[K] = \ sum_ \ left.i = 1 \右^ \ left.r \ right.tree [I] *(R-I + 1)= R * \ sum_ \ left.i = 1 \右^ RTREE [I ] - \ sum_ \ left.i = 1 \右^ \ left.r \ right.tree [I] *(I-1)\]。
\(CF [I] =ツリー[I] *(I-1 )\) 则我们要求
\ [\ sum_ \ left.i = 1 \右^ RA [I] = R * \ sum_ \ left.i = 1つの\右^ RTREE [I] - 。\ sum_ \左。私は1つの\権利を=。^ \ left.r \ right.cf [I] \]

//初值
for(int i=1;i<=n;i++){
    scanf("%lld",&x);
    change(tree,i,x-now);
    change(cf,i,(i-1)*(x-now));
    now=x;
} 
//区间修改 区间为[x,y]
change(tree,x,k);
change(tree,y+1,-k);
change(cf,x,k*(x-1));
change(cf,y+1,-k*y);
//区间查询 区间为[x,y]
ll sum1=y*query(tree,y)-(x-1)*query(tree,x-1);
ll sum2=query(cf,y)-query(cf,x-1);
printf("%lld\n",sum1-sum2);

より優れたライティングを更新

inline int lowbit(int x){return x&-x;}
void change(int x,ll k){
    ll p=x;
    while(x<=n){
        tree[x]+=k;
        cf[x]+=(p-1)*k;
        x+=lowbit(x);           
    }
}
ll query(int x){
    ll ans=0,p=x;
    while(x){
        ans+=p*tree[x]-cf[x];
        x-=lowbit(x);
    }
    return ans;
}
//修改
change(x,k);
change(y+1,-k);
//查询
printf("%lld\n",query(y)-query(x-1));

第三に、ツリーの高次元配列

(A)前のスキル

もっと見つけることができますhttps://www.cnblogs.com/Miracevin/p/9778266.html

プレフィックスとインクルージョン排除を利用することができる差動および解決に詳細着手することはありません

接頭辞と高次元のサブセットは、セット状態とAを計算することです

そして、2次元の接頭辞

for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
         sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];

若しくは

for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
        a[i][j]+=a[i][j-1];
for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
        a[i][j]+=a[i-1][j];

逆プレフィックスとオーバーです

高次元と2つの要素のプレフィックス(wが最高寸法を示します)

for(int i=0;i<w;i++)
    for(int j=0;j<(1<<w);j++)
        if(j&(1<<i))f[j]+=f[j^(1<<i)];

(B)ツリーの二次元アレイの基礎

修正のシングルポイント、クエリーインターバル

inline int lowbit(int x){return x&(-x);}
void change(int x,int y,ll k){
    for(int i=x;i<=n;i+=lowbit(i))
    for(int j=y;j<=m;j+=lowbit(j))
        tree[i][j]+=k;
}
ll query(int x,int y){
    ll ans=0;
    for(int i=x;i>=1;i-=lowbit(i))
    for(int j=y;j>=1;j-=lowbit(j))
        ans+=tree[i][j];
    return ans;
}
//查询
query(x2,y2)-query(x_1-1,y2)-query(x2,y_1-1)+query(x_1-1,y_1-1)

(C)ツリーの二次元アレイの範囲

同様の一次元の場合、得られる
\ [\ sum_ \ left.i = 1 \右^ X \ sum_ \ left.j = 1 \右^雅[I] [J] = X * Y \ sum_ \左。 私は1を= \右。^ X \ sum_ \ left.j = 1 \右。^ ytree [I] [J] -y * \ sum_ \ left.i = 1 \右。^ X \ sum_ \ left.j = 1 \右^ ytree [I] [J] *(I-1)\\ - X * \ sum_ \ left.i = 1 \右^ X \ sum_ \ left.j = 1 \右^ ytree [.. I] [J] *(j -1)+ \ sum_ \ left.i = 1 \右^ X \ sum_ \ left.j = 1 \右^ ytree [I] [J] *(I-1) *(J-1)\]
および除外と同様に、n次元の場合に拡張することができます

再度コードCSP(4メンテナンスアレイ更新、照会もたらす係数)を更新した後

おすすめ

転載: www.cnblogs.com/Robert-JYH/p/11845212.html