フェンウィックツリーの詳細とテンプレート

 

シングルポイント更新

ボイド更新(int型 X、int型 Yを、INT N-){
     ためint型 I = Xを、I <= N; Iは+ = lowbit(I))     // Xが更新された位置であり、yは更新数であり、nはアレイ最大値 
        C [I] + = Y。
}

 

クエリ間隔(1 - X)

INT getsum(INT X){
     int型 ANS = 0 int型 ; I; I- = I = xをlowbit(I)) + = C [i]は、
    返す歳;
}

高度な操作

逆に探しています

アレイのため、それは離散Bとして扱われる[]。インターバルクエリ、次の一点を修正

無効更新(int型P)
{
    一方、(P <= N)
    {
        [P] ++ ;
        P + = lowbit(P)。
    }
}
 
int型 getsum(int型P)
{
    int型のres = 0 ;
    しばらく(P)
        RES + = A [P]、P - = lowbit(P)。
    リターンのres;
}

の数と逆の順序:

以下のためにint型 i = 1 ; iが++; iが<= N ){
    更新(B [I] + 1 )。
    RES + = I-getsum(B [I] + 1 )。
}

RESは、Bを留意すべきで、依頼[i]が0より大きくなければならない、逆の順序の数であります

 

最大間隔を求めて

アップデート(int型 I、int型のV)
{
    一方、(I <= MAXY)
    {
        T [I] = MAX(T [i]は、V)。
        I + = lowbit(I)。
    }
}
int型のクエリ(int型I)
{
    int型 ANS = 0 ;
    しばらく(I)
    { = MAX(年のT [i])と、
        I - = lowbit(I)。
    }
    返す歳;
}

 

 

INT lowbit(INT X){
     戻り X& - X。
}
無効追加(int型の P、int型 X){     // この関数は直接ツリーの配列を変更するために使用されて
    しばらく(P <= N-){
        C [P] + =のX。
        P + = lowbit(P)。
    }
}

ボイド range_add(int型 L、INT R&LT、INT X){   // 間隔に[L、R]プラスX 
    追加(L、X)を、
    追加(R + 1、 - X)。
}
INT(ASK INT P){   // 単一点クエリ
    INT RES = 0 ;
     一方、(P){
        A + B [P]。
        P - = lowbit(P)。
    }
    リターンのres;
}

 

ボイド追加(LL pを、LLのX){
     ためint型のI = P; iは= N <; I + = I& - i)を
        SUM1 [I] + = X、SUM2 [I] + = X * P。
}
void range_add(ll l, ll r, ll x){
    add(l, x), add(r + 1, -x);
}
ll ask(ll p){
    ll res = 0;
    for(int i = p; i; i -= i & -i)
        res += (p + 1) * sum1[i] - sum2[i];
    return res;
}
ll range_ask(ll l, ll r){
    return ask(r) - ask(l - 1);
}

用这个做区间修改区间求和的题,无论是时间上还是空间上都比带lazy标记的线段树要优。

 

void add(int x, int y, int z){ //将点(x, y)加上z
    int memo_y = y;
    while(x <= n){
        y = memo_y;
        while(y <= n)
            tree[x][y] += z, y += y & -y;
        x += x & -x;
    }
}
void ask(int x, int y){//求左上角为(1,1)右下角为(x,y) 的矩阵和
    int res = 0, memo_y = y;
    while(x){
        y = memo_y;
        while(y)
            res += tree[x][y], y -= y & -y;
        x -= x & -x;
    }
}

void add(int x, int y, int z){ 
    int memo_y = y;
    while(x <= n){
        y = memo_y;
        while(y <= n)
            tree[x][y] += z, y += y & -y;
        x += x & -x;
    }
}
void range_add(int xa, int ya, int xb, int yb, int z){
    add(xa, ya, z);
    add(xa, yb + 1, -z);
    add(xb + 1, ya, -z);
    add(xb + 1, yb + 1, z);
}
void ask(int x, int y){
    int res = 0, memo_y = y;
    while(x){
        y = memo_y;
        while(y)
            res += tree[x][y], y -= y & -y;
        x -= x & -x;
    }
}

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;
ll read(){
    char c; bool op = 0;
    while((c = getchar()) < '0' || c > '9')
        if(c == '-') op = 1;
    ll res = c - '0';
    while((c = getchar()) >= '0' && c <= '9')
        res = res * 10 + c - '0';
    return op ? -res : res;
}
const int N = 205;
ll n, m, Q;
ll t1[N][N], t2[N][N], t3[N][N], t4[N][N];
void add(ll x, ll y, ll z){
    for(int X = x; X <= n; X += X & -X)
        for(int Y = y; Y <= m; Y += Y & -Y){
            t1[X][Y] += z;
            t2[X][Y] += z * x;
            t3[X][Y] += z * y;
            t4[X][Y] += z * x * y;
        }
}
void range_add(ll xa, ll ya, ll xb, ll yb, ll z){ //(xa, ya) 到 (xb, yb) 的矩形
    add(xa, ya, z);
    add(xa, yb + 1, -z);
    add(xb + 1, ya, -z);
    add(xb + 1, yb + 1, z);
}
ll ask(ll x, ll y){
    ll res = 0;
    for(int i = x; i; i -= i & -i)
        for(int j = y; j; j -= j & -j)
            res += (x + 1) * (y + 1) * t1[i][j]
                - (y + 1) * t2[i][j]
                - (x + 1) * t3[i][j]
                + t4[i][j];
    return res;
}
ll range_ask(ll xa, ll ya, ll xb, ll yb){
    return ask(xb, yb) - ask(xb, ya - 1) - ask(xa - 1, yb) + ask(xa - 1, ya - 1);
}
int main(){
    n = read(), m = read(), Q = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            ll z = read();
            range_add(i, j, i, j, z);
        }
    }
    while(Q--){
        ll ya = read(), xa = read(), yb = read(), xb = read(), z = read(), a = read();
        if(range_ask(xa, ya, xb, yb) < z * (xb - xa + 1) * (yb - ya + 1))
            range_add(xa, ya, xb, yb, a);
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++)
            printf("%lld ", range_ask(i, j, i, j));
        putchar('\n');
    }
    return 0;
}

 

おすすめ

転載: www.cnblogs.com/smallhester/p/11345721.html
おすすめ