BZOJ 1176 Mokia CDQ分治+树状数组
1176: [Balkan2007]Mokia
Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 1854 Solved: 821
[Submit][Status][Discuss]
Description
维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.
Input
第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小
接下来每行为一下三种输入之一(不包含引号):
"1 x y a"
"2 x1 y1 x2 y2"
"3"
输入1:你需要把(x,y)(第x行第y列)的格子权值增加a
输入2:你需要求出以左上角为(x1,y1),右下角为(x2,y2)的矩阵内所有格子的权值和,并输出
输入3:表示输入结束
Output
对于每个输入2,输出一行,即输入2的答案
Sample Input
0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
Sample Output
3
5
5
HINT
保证答案不会超过int范围
Solution
CDQ分治+树状数组裸题,矩阵分成四个点统计,单点更新。
Code
#include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <algorithm> #include <iostream> using namespace std; const int maxn = 2000005; const int maxm = 160000+10005; int s, w, ans[maxm]; struct Node { int op, id, x, y, k, to; Node (int op = 0, int id = 0, int x = 0, int y = 0, int k = 0, int to = 0): op(op), id(id), x(x), y(y), k(k), to(to) {} bool operator < (const Node &AI) const { if (x == AI.x && y == AI.y) return op < AI.op; if (x == AI.x) return y < AI.y; return x < AI.x; } }q[maxm], temp[maxm]; struct BIT { int c[maxn+10]; int lowbit(int x) { return x & -x; } void update(int x, int d) { while (x <= w) { c[x] += d; x += lowbit(x); } } int query(int x) { int ret = 0; while (x > 0) { ret += c[x]; x -= lowbit(x); } return ret; } }T; void cdq(int l, int r) { if (l == r) return ; int mid = (l+r)>>1; for (int i = l; i <= r; ++i) { if (q[i].id <= mid && q[i].op == 1) T.update(q[i].y, q[i].k); if (q[i].id > mid && q[i].op == 2) ans[q[i].to] += q[i].k*T.query(q[i].y); } for (int i = l; i <= r; ++i) if (q[i].id <= mid && q[i].op == 1) T.update(q[i].y, -q[i].k); int t1 = l-1, t2 = mid; for (int i = l; i <= r; ++i) if (q[i].id <= mid) temp[++t1] = q[i]; else temp[++t2] = q[i]; for (int i = l; i <= r; ++i) q[i] = temp[i]; cdq(l, mid), cdq(mid+1, r); } int main() { scanf("%d %d", &s, &w); w += 2; int oper, cnt = 0, cnt_2 = 0; while (~scanf("%d", &oper) && oper != 3) { if (oper == 1) { int x, y, d; scanf("%d %d %d", &x, &y, &d); x += 2, y += 2; q[++cnt] = Node(1, cnt, x, y, d, 0); } else { int x1, y1, x2, y2; scanf("%d %d %d %d", &x1, &y1, &x2, &y2); x1 += 2, y1 += 2, x2 += 2, y2 += 2; cnt_2 ++; ans[cnt_2] = s*(x2-x1+1)*(y2-y1+1); q[++cnt] = Node(2, cnt, x2, y2, 1, cnt_2); q[++cnt] = Node(2, cnt, x1-1, y2, -1, cnt_2); q[++cnt] = Node(2, cnt, x2, y1-1, -1, cnt_2); q[++cnt] = Node(2, cnt, x1-1, y1-1, 1, cnt_2); } } sort(q+1, q+cnt+1); cdq(1, cnt); for (int i = 1; i <= cnt_2; ++i) printf("%d\n", ans[i]); return 0; }
Nothing is impossible!