序文
私は信じている「修正の単一の点を、クエリー間隔」誰もがツリーまたは「ゾーン変更、問い合わせの単一のポイントを」フェンウィックなり、ブロガーは、詳細には触れません。
しかし、ブロガーは、今日は魔法のアルゴリズム(ブロガーあまりにも多くの食べ物)、それはフェンウィックツリーのメンテナンスを使用することができた「セクションには、クエリー間隔を変更します。」
修正のシングルポイント、クエリーインターバル
プレフィックスで、クエリを最適化し、調整修正\(\シータ(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;
}