Luogu P4514 上帝造题的七分钟 (二维树状数组模板)

gate

二维树状数组,区间修改,区间查询

对于区间$(x,y)$,用差分数组来维护,每次从$(1,1)$加到$(i,j)$

可以发现,$t[1][1]$被加了$x*y$次,$t[1][2]$被加了$(x-1)*y$次…

那么区间$(x,y)$的和即为

$∑i=(1,x)∑j=(1,y)$ $t[i][j]*(x-i+1)*(y-j+1)$

把括号打开

$∑i=(1,x)∑j=(1,y)$ $t[i][j]*(x+1)*(y+1) + t[i][j]*i*(y+1) + t[i][j]*j*(x+1) + t[i][j]*i*j$

所以维护四个数组,分别表示:$t[i][j],t[i][j]*i,t[i][j]*j,t[i][j]*i*j$

然后查询的时候,乘上对应的$x+1$和$y+1$。

修改一段区间$(x_1-x_2,y_1-y_2)$时,则有

$+(x_1,y_2),-(x_2+1,y_1),-(x_1,y_2+1),+(x_2+1,y_2+1)$

查询一段区间$(x_1-x_2,y_1-y_2)$时,则有

$+(x_1-1,y_2-1),-(x_2,y_1-1),-(x_1-1,y_2),+(x_2,y_2)$

代码如下...

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
using namespace std;

int n,m,a,b,c,d,k;
int t[5][2050][2050];
char op;

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

int lowbit(int x) {
    return x & (-x);
}

void update(int x,int y,int k) {
    for(int i = x; i <= n; i += lowbit(i))
        for(int j = y; j <= m; j += lowbit(j)) {
            t[1][i][j] += k;
            t[2][i][j] += k * x;
            t[3][i][j] += k * y;
            t[4][i][j] += k * x * y;
        }
}

int query(int x,int y) {
    int ret = 0;
    for(int i = x; i; i -= lowbit(i))
        for(int j = y; j; j -= lowbit(j)) {
            ret += t[1][i][j] * (x+1) * (y+1);
            ret -= t[2][i][j] * (y+1);
            ret -= t[3][i][j] * (x+1);
            ret += t[4][i][j];
        }
    return ret;
}

void getupdate(int a,int b,int c,int d,int k) {
    update(c+1,d+1,k);
    update(c+1,b,-k);
    update(a,d+1,-k);
    update(a,b,k);
}

int getquery(int a,int b,int c,int d) {
    return query(c,d) - query(c,b-1) - query(a-1,d) + query(a-1,b-1);
}

int main() {
    scanf("%c%d%d",&op,&n,&m);
    while(cin >> op) {
        a = read(),b = read(),c = read(),d = read();
        if(op == 'L') {
            k = read();
            getupdate(a,b,c,d,k);
        }
        if(op == 'k')
            printf("%d
",getquery(a,b,c,d));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/mogeko/p/11842984.html