# [TYVJ P1716/BZOJ 3132 上帝造题的七分钟] 二维树状数组区间修改、区间查询

## 1. 题目链接

[TYVJ P1716 上帝造题的七分钟]

## 3. 解题思路

BZOJ 3132这个题目好像找不到了？就在TYVJ上找到这个题目了。

sum=i=1xj=1y[di,j(xi+1)(yi+1)]=i=1xj=1y{di,j[(x+1)(y+1)(x+1)j(y+1)i+ij]}=i=1xj=1y[(x+1)(y+1)dij(x+1)jdij(y+1)idij+ijdij]

## 4. 实现代码

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int MAXN = 2048 + 1;

int n, m;
// 输入挂
namespace IO {
const int MT = 10 * 1024 * 1024;  /// 10MB 请注意输入数据的大小！！！
char IO_BUF[MT];
int IO_PTR, IO_SZ;
/// 要记得把这一行添加到main函数第一行！！！
void begin() {
IO_PTR = 0;
IO_SZ = fread (IO_BUF, 1, MT, stdin);
}
template<typename T>
inline bool scan_d (T & t) {
while (IO_PTR < IO_SZ && IO_BUF[IO_PTR] != '-' && (IO_BUF[IO_PTR] < '0' || IO_BUF[IO_PTR] > '9'))
IO_PTR ++;
if (IO_PTR >= IO_SZ) return false;
bool sgn = false;
if (IO_BUF[IO_PTR] == '-') sgn = true, IO_PTR ++;
for (t = 0; IO_PTR < IO_SZ && '0' <= IO_BUF[IO_PTR] && IO_BUF[IO_PTR] <= '9'; IO_PTR ++)
t = t * 10 + IO_BUF[IO_PTR] - '0';
if (sgn) t = -t;
return true;
}
inline bool scan_s (char s[]) {
while (IO_PTR < IO_SZ && (IO_BUF[IO_PTR] == ' ' || IO_BUF[IO_PTR] == '\n') ) IO_PTR ++;
if (IO_PTR >= IO_SZ) return false;
int len = 0;
while (IO_PTR < IO_SZ && IO_BUF[IO_PTR] != ' ' && IO_BUF[IO_PTR] != '\n')
s[len ++] = IO_BUF[IO_PTR], IO_PTR ++;
s[len] = '\0';
return true;
}
template<typename T>
void print(T x) {
static char s[33], *s1; s1 = s;
if (!x) *s1++ = '0';
if (x < 0) putchar('-'), x = -x;
while(x) *s1++ = (x % 10 + '0'), x /= 10;
while(s1-- != s) putchar(*s1);
}
template<typename T>
void println(T x) {
print(x); putchar('\n');
}
};

template<class T>
struct BIT_2D {
struct Core {
T C[4][MAXN][MAXN];
void I() { memset(C, 0, sizeof(C)); }
inline T lowbit(const T& x) { return x & (-x); }
void update(const int& x0, const int& y0, const T& val) {
for(int x = x0; x <= n; x += x & (-x)) {
for(int y = y0; y <= m; y += y & (-y)) {
C[0][x][y] += val;
C[1][x][y] += val * x0;
C[2][x][y] += val * y0;
C[3][x][y] += val * x0 * y0;
}
}
}
T query(const int& x0, const int& y0) {
T ret = 0;
for(int x = x0; x > 0; x -= x & (-x)) {
for(int y = y0; y > 0; y -= y & (-y)) {
ret += C[0][x][y] * (x0 + 1) * (y0 + 1);
ret -= C[1][x][y] * (y0 + 1);
ret -= C[2][x][y] * (x0 + 1);
ret += C[3][x][y];
}
}
return ret;
}
};
Core core;
void update(const int& x0, const int& y0, const int& x1, const int& y1, const int& val) {
int dx[4] = {x0, x1 + 1, x0, x1 + 1};
int dy[4] = {y0, y1 + 1, y1 + 1, y0};
int v[4] = {val, val, -val, -val};
for(int i = 0; i < 4; ++i) {
core.update(dx[i], dy[i], v[i]);
}
}
int query(const int& x0, const int& y0, const int& x1, const int& y1) {
int ret = 0;
int dx[4] = {x0 - 1, x1, x0 - 1, x1};
int dy[4] = {y0 - 1, y1, y1, y0 - 1};
int v[4] = {1, 1, -1, -1};
for(int i = 0; i < 4; ++i) {
ret += v[i] * core.query(dx[i], dy[i]);
}
return ret;
}
};
BIT_2D<int> bit;

char op[5];
int x[2], y[2], delta;

int main() {
#ifdef ___LOCAL_WONZY___
freopen("input.txt", "r", stdin);
#endif // ___LOCAL_WONZY___
IO::begin();
while(IO::scan_s(op)) {
if(op[0] == 'X') {
IO::scan_d(n);
IO::scan_d(m);
//            a.I(), b.I(), c.I(), d.I();
continue;
}
IO::scan_d(x[0]);
IO::scan_d(y[0]);
IO::scan_d(x[1]);
IO::scan_d(y[1]);
if(op[0] == 'k') {
IO::println(bit.query(x[0], y[0], x[1], y[1]));
} else {
IO::scan_d(delta);
bit.update(x[0], y[0], x[1], y[1], delta);
}
}
return 0;
}

#### 树状数组整理（2.区间修改、二维）

2013-03-29 21:37:42

#### 一维 + 二维树状数组 + 单点更新 + 区间更新 详解

2015-08-08 00:13:05

#### 【小结】树状数组的区间修改与区间查询

2015-02-26 21:46:50

#### POJ - 2155 Matrix (二维树状数组 + 区间修改 + 单点求值 或者 二维线段树 + 区间更新 + 单点求值)

2015-08-07 20:16:33

#### 详解树状数组 区间修改求和

2017-07-11 20:22:18

#### 二维树状数组上帝造题的七分钟（tyvj1716）

2016-07-22 15:09:31

#### 二维树状数组的区间加减及查询 tyvj 1716 上帝造题的七分钟

2014-06-17 14:06:20

#### POJ 2155 Matrix （二维树状数组，区间更新，点查找）

2015-08-26 15:50:56

#### poj2155-二维树状数组 区间更新 单点查询

2017-05-12 20:35:12

#### [BZOJ3132]上帝造题的七分钟

2016-03-21 19:29:54

## 不良信息举报

[TYVJ P1716/BZOJ 3132 上帝造题的七分钟] 二维树状数组区间修改、区间查询