【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

Sample Output

3
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 }

 

posted @ 2015-07-12 18:21  Lightning34  阅读(215)  评论(0编辑  收藏  举报