[アルゴリズム]フェンウィックツリー

序文

私は信じている「修正の単一の点を、クエリー間隔」誰もがツリーまたは「ゾーン変更、問い合わせの単一のポイントを」フェンウィックなり、ブロガーは、詳細には触れません。
しかし、ブロガーは、今日は魔法のアルゴリズム(ブロガーあまりにも多くの食べ物)、それはフェンウィックツリーのメンテナンスを使用することができた「セクションには、クエリー間隔を変更します。」

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

プレフィックスで、クエリを最適化し、調整修正\(\シータ(log_2nを)\ )

間隔、問い合わせの単一の点を変更します。

柯への上記差動フェンウィックツリー、

間隔を変更し、間隔のクエリ

詳細なアルゴリズム

元の配列の提供\(\)を添え字から、長さ\(N-を\)、\ (a_iを-A_ {I-1} \)と呼ばれる\(\ delta_i \) 我々は必要\(A_0 = 0 \)
次に、
\ [a_iを= \ sum_ {J
= 1} ^ I {\デルタ} _i \] 和式二十から二オフセットを証明することは容易である場合。
したがって、もし\(中X \ [1、N-] \)
\ [\ sum_ {I = 1} ^ xa_i = \ sum_ {I = 1} ^ X \ sum_ {J = 1} ^ I {\デルタ} _J = \ sum_ {I = 1}
回{\デルタ} _i \] \ ^ X(X-i + 1)のように
\ [\ sum_ {i = 1 } ^ xa_i =(X + 1)\ sum_ {i = 1 } ^ X {\デルタ} _i-
\ sum_ {i = 1} ^ X {\デルタ} _i回\ I \] 最後に、我々は、2つの差動ハッピーツリーアレイ、維持
保守\(D_Iを\) その他をメンテナンス\(私は\ D_I \回)

コード

namespace FenWick{
    #define lowbit(x) (x&(-x))
    #define ll long long
    #define MAXN 1000005
    int n; 
    ll d1[MAXN] , d2[MAXN];
    void modifySuffix(int x, ll val){
        for (int i = x; i <= n; i += lowbit(i))
            d1[i] += val, d2[i] += val * x;
    }
    inline void modify(int x, int y, ll val){
        modifySuffix(x, val), modifySuffix(y + 1, -val);
    }
    ll queryPrefix(int x){
        ll res = 0;
        for (int i = x; i; i -= lowbit(i))
            res += (x + 1) * d1[i] - d2[i];
        return res;
    }
    inline ll query(int x, int y){
        return (queryPrefix(y) - queryPrefix(x - 1));
    }
};

練習

[LOJ132]フェンウィックの木3:間隔を変更し、間隔のクエリ

#include <cstdio>

namespace FenWick{
    #define lowbit(x) (x&(-x))
    #define ll long long
    #define MAXN 1000005
    int n; 
    ll d1[MAXN] , d2[MAXN];
    void modifySuffix(int x, ll val){
        for (int i = x; i <= n; i += lowbit(i))
            d1[i] += val, d2[i] += val * x;
    }
    inline void modify(int x, int y, ll val){
        modifySuffix(x, val), modifySuffix(y + 1, -val);
    }
    ll queryPrefix(int x){
        ll res = 0;
        for (int i = x; i; i -= lowbit(i))
            res += (x + 1) * d1[i] - d2[i];
        return res;
    }
    inline ll query(int x, int y){
        return (queryPrefix(y) - queryPrefix(x - 1));
    }
};

using namespace FenWick;

ll read(){
    ll x = 0; int zf = 1; char ch = ' ';
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') zf = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
}

int main(){
    n = read(); int q = read();
    for (int i = 1; i <= n; ++i)
        modify(i, i, read());
    while (q--){
        int op = read(), l = read(), r = read(), x;
        switch(op){
            case 1:
                x = read();
                modify(l, r, x);
                break;
            case 2:
                printf("%lld\n", query(l, r));
                break;
            default:
                puts("Invalid Command!");
                break;
        }
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/linzhengmin/p/11073801.html