三百行代码演绎树状数组基础全家桶(一维树状数组 + 二维树状数组)

/*
#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

template<class T> inline void read(T &x){
    x = 0; register char c = getchar(); register bool f = 0;
    while(!isdigit(c)) f ^= c == '-', c = getchar();
    while(isdigit(c)) x = x * 10 + c - '0', c = getchar();
    if(f) x = -x;
}

template<class T> inline void print(T x){
    if(x < 0) putchar('-'), x = -x;
    if(x > 9) print(x / 10);
    putchar('0' + x % 10);
}
*/

/*单点修改,区间查询
const int N = 5e5 + 10;
int n, m;
int a[N], tree[N];
inline int lowbit(int x){
    return x & -x;
}
inline void update(int x, int v){
    for(; x <= n; x += lowbit(x)){
        tree[x] += v;
    }
}
inline int query(int x){
    int res = 0;
    for(; x; x -= lowbit(x)){
        res += tree[x];
    }
    return res;
}

int main(){
    read(n), read(m);
    for(int i = 1; i <= n; i ++) read(a[i]), update(i, a[i]);
    for(int i = 1, opt, x, y; i <= m; i ++){
        read(opt);
        if(opt == 1){
            read(x), read(y);
            update(x, y);
        }else
        if(opt == 2){
            read(x), read(y);
            print(query(y) - query(x - 1));
            puts("");
        }
    }
    return 0;
}
*/
/*区间修改,单点查询
#define int long long
const int N = 1e6 + 10;
int n, m;
int a[N], tree[N];

inline int lowbit(int x){
    return x & -x;
}
inline void update(int x, int v){
    for(; x <= n; x += lowbit(x)){
        tree[x] += v;
    }
}
inline int query(int x){
    int res = 0;
    for(; x; x -= lowbit(x)){
        res += tree[x];
    }
    return res;
}

signed main(){
    read(n), read(m);
    for(int i = 1; i <= n; i ++){
        read(a[i]);
    }
    update(1, a[1]);
    for(int i = 2; i <= n; i ++){
        update(i, a[i] - a[i - 1]);
    }
    for(int i = 1, opt, a, b, c; i <= m; i ++){
        read(opt);
        if(opt == 1){
            read(a), read(b), read(c);
            update(a, c), update(b + 1, -c);
        }else
        if(opt == 2){
            read(a);
            print(query(a));
            puts("");
        }
    }
    return 0;
}*/
/*区间查询,区间修改
#define int long long
const int N = 1e6 + 10;
int n, m, a[N];
int tree1[N], tree2[N];

inline int lowbit(int x){
    return x & -x;
}
inline void update(int x, int v){
    int p = x;
    for(; x <= n; x += lowbit(x)){
        tree1[x] += v, tree2[x] += v * p;
    }
}
inline void range_update(int l, int r, int v){
    update(l, v), update(r + 1, -v);
}
inline int query(int x){
    int res = 0, p = x;
    for(; x; x -= lowbit(x)){
        res += (p + 1) * tree1[x] - tree2[x];
    }
    return res;
}
inline int range_query(int l, int r){
    return query(r) - query(l - 1);
}

signed main(){
    read(n), read(m);
    for(int i = 1; i <= n; i ++) read(a[i]);
    for(int i = 1; i <= n; i ++) update(i, a[i] - a[i - 1]);
    for(int i = 1, opt, a, b, c; i <= m; i ++){
        read(opt);
        if(opt == 1){
            read(a), read(b), read(c);
            range_update(a, b, c);
        }else
        if(opt == 2){
            read(a), read(b);
            print(range_query(a, b));
            puts("");
        }
    }
    return 0;
}*/
/************************************************************************************
接下来是二维树状数组
一维树状数组中,tree[x]:右端点为x,长度为lowbit(x)的区间的区间和。
二维树状数组中,tree[x][y]:右下角为(x, y),高为lowbit(x),宽为 lowbit(y)的区间的区间和。
************************************************************************************/
//单点修改,区间查询
/*inline void update(int x, int y, int v){//将点(x, y)加上 z
    int memo_y = y;
    while(x <= n){
        y = memo_y;
        while(y <= n){
            tree[x][y] += v, y += lowbit(y);
        }
        x += lowbit(x);
    }
}
inline void query(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 -= lowbit(y);
        }
        x -= lowbit(x);
    }
}*/
//区间修改,单点查询
/*inline void update(int x, int y, int v){
    int memo_y = y;
    while(x <= n){
        y = memo_y;
        while(y <= n){
            tree[x][y] += v, y += lowbit(y);
        }
        x += lowbit(x);
    }
}
inline void range_update(int x1, int y1, int x2, int y2, int v){
    update(x1, y1, v);
    update(x1, y2 + 1, -v);
    update(x2 + 1, y1, -v);
    update(x2 + 1, y2 + 1, v);
}
inline void query(int x, int y){
    int res = 0, memo_y = y;
    while(x){
        y = memo_y;
        while(y)
            res += tree[x][y], y -= lowbit(y);
    }
    x -= lowbit(x);
}*/
//重点————区间修改,区间查询
//P4514 上帝造题的七分钟
#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

template<class T> inline void read(T &x){
    x = 0; register char c = getchar(); register bool f = 0;
    while(!isdigit(c)) f ^= c == '-', c = getchar();
    while(isdigit(c)) x = x * 10 + c - '0', c = getchar();
    if(f) x = -x;
}

template<class T> inline void print(T x){
    if(x < 0) putchar('-'), x = -x;
    if(x > 9) print(x / 10);
    putchar('0' + x % 10);
}
inline char readc(){
    char ch;
    while(ch = getchar(), ch != EOF && !isalpha(ch));
    return ch;
}
const int N = 2049;
int n, m; char c;
int tree[4][N][N];
inline int lowbit(int x){
    return x & -x;
}
inline void update(int x, int y, int v){
    if(x < 1 || n < x || y < 1 || m < y) return;
    for(int i = x; i <= n; i += lowbit(i)){
        for(int j = y; j <= m; j += lowbit(j)){
            tree[0][i][j] += v;
            tree[1][i][j] += v * x;
            tree[2][i][j] += v * y;
            tree[3][i][j] += v * x * y;
        }
    }
}
inline void range_update(int x1, int y1, int x2, int y2, int v){
    update(x1, y1, v);
    update(x1, y2 + 1, -v);
    update(x2 + 1, y1, -v);
    update(x2 + 1, y2 + 1, v);
}
inline int query(int x, int y){
    int res = 0;
    for(int i = x; i; i -= lowbit(i)){
        for(int j = y; j; j -= lowbit(j)){
            res += (x + 1) * (y + 1) * tree[0][i][j]
            - (y + 1) * tree[1][i][j]
            - (x + 1) * tree[2][i][j]
            + tree[3][i][j];
        }         
    }
    return res;
}
inline int range_query(int x1, int y1, int x2, int y2){
    return query(x2, y2) - query(x2, y1 - 1) - query(x1 - 1, y2) + query(x1 - 1, y1 - 1);
}
signed main(){
    /*read(n), read(m), read(Q);
    for(int i = 1; i <= n; i ++){
        for(int j = 1; j <= n; j ++){
            int z; read(z);
            range_update(i, j, i, j, z);
        }
    }
    while(Q --){
        int y1, x1, y2, x2, z, a;
        read(y1), read(x1), read(y2), read(x2), read(z), read(a);
        if(range_query(x1, y1, x2, y1) < z * (x2 - x1 + 1) * (y2 - y1 + 1))
            range_update(x1, y1, x2, y2, a);
    }
    for(int i = 1; i <= n; i ++){
        for(int j = 1; j <= m; j ++)
            print(range_query(i, j, i, j)); cout << " ";
        puts("");
    }
    return 0;*/
    readc();
    read(n), read(m);
    int x1, x2, y1, y2, v;
    while(c = readc(), c != EOF){
        read(x1), read(y1), read(x2), read(y2);
        if(c == 'L'){
            read(v);
            range_update(x1, y1, x2, y2, v);
        }else
        if(c == 'k'){
            print(range_query(x1, y1, x2, y2));
            puts("");
        }
    }
    return 0;
}

 

posted @ 2022-03-23 22:52  Altwilio  阅读(149)  评论(1编辑  收藏  举报