【BZOJ 1176 2683】Mokia
Description
维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.(在2683中,没有S,初始值为0)。
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范围
分析:
对操作进行分治,左边的修改必定会影响右边的查询,这一部分只要对x排序,做树状数组就好了。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 struct A 6 { 7 int x, y, pos, ctrl, ans; 8 } t[200010], q[200010]; 9 10 inline bool cmp(const A &a, const A &b) 11 { 12 return a.pos < b.pos; 13 } 14 15 int s, w, k, x, y, a, b, cnt; 16 int key[2000010], late[2000010], now; 17 18 void modify(int pos, int data) 19 { 20 for ( ; pos <= w + 1; pos += pos & -pos) 21 { 22 if (late[pos] != now) key[pos] = 0; 23 late[pos] = now, key[pos] += data; 24 } 25 } 26 27 int query(int pos) 28 { 29 int ret = 0; 30 for ( ; pos; pos -= pos & -pos) 31 if (late[pos] == now) ret += key[pos]; 32 return ret; 33 } 34 35 void cdq(int left, int right) 36 { 37 if (left == right) return; 38 int mid = left + right >> 1; 39 cdq(left, mid); cdq(mid + 1, right); 40 now++; 41 for (int i = mid + 1, j = left; i <= right; i++) 42 { 43 for ( ; j <= mid && q[j].x <= q[i].x; j++) 44 if (q[j].ctrl == 0) modify(q[j].y, q[j].ans); 45 if (q[i].ctrl > 0) q[i].ans += query(q[i].y); 46 } 47 for (int i = left, j = left, k = mid + 1; i <= right; i++) 48 { 49 if ((q[j].x <= q[k].x && j <= mid) || k > right) 50 t[i] = q[j++]; 51 else t[i] = q[k++]; 52 } 53 memcpy(q + left, t + left, sizeof(q[0]) * (right - left + 1)); 54 } 55 56 int main() 57 { 58 scanf("%d%d", &s, &w); 59 while (k != 3) 60 { 61 scanf("%d", &k); 62 if (k == 1) 63 { 64 scanf("%d%d%d", &x, &y, &a); 65 cnt++, q[cnt] = (A) {x + 1, y + 1, cnt, 0, a}; 66 } 67 if (k == 2) 68 { 69 scanf("%d%d%d%d", &x, &y, &a, &b); 70 a++, b++; 71 cnt++, q[cnt] = (A) {x, y, cnt, 1, x * y * s}; 72 cnt++, q[cnt] = (A) {a, b, cnt, 2, a * b * s}; 73 cnt++, q[cnt] = (A) {a, y, cnt, 2, a * y * s}; 74 cnt++, q[cnt] = (A) {x, b, cnt, 2, x * b * s}; 75 } 76 } 77 cdq(1, cnt); 78 std::sort(q + 1, q + cnt + 1, cmp); 79 for (int i = 1; i <= cnt; i++) 80 { 81 if (q[i].ctrl == 1) 82 { 83 printf("%d\n", q[i].ans + q[i + 1].ans - q[i + 2].ans - q[i + 3].ans); 84 } 85 } 86 }
Your eyes light up the world when you smile.