BZOJ 1176: [Balkan2007]Mokia

1176: [Balkan2007]Mokia

Time Limit: 30 Sec  Memory Limit: 162 MB
Submit: 2012  Solved: 896
[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

Sample Output

3
5

HINT

 

保证答案不会超过int范围

 

Source

 
[Submit][Status][Discuss]

 

CDQ分治。

 

 1 #include <bits/stdc++.h>
 2 const int maxn = 400005;
 3 const int maxw = 2000005;
 4 int tr[maxw], w;
 5 inline void add(int t, int k) {
 6     for (; t <= w; t += t&-t)
 7         tr[t] += k;
 8 }
 9 inline int ask(int t) {
10     int ret = 0;
11     for (; t; t -= t&-t)
12         ret += tr[t];
13     return ret;
14 }
15 inline int ask(int a, int b) {
16     return ask(b) - ask(a - 1);
17 }
18 struct data {
19    int k, a, b, c, d, t, p; 
20 }s[maxn]; int tot = 1;
21 int ans[maxn], cnt = 1;
22 inline void add(void) {
23     scanf("%d%d%d", &s[tot].a, &s[tot].b, &s[tot].c), s[tot].t = tot, s[tot++].k = 1;
24 }
25 inline void qry(void) {
26     int x1, x2, y1, y2; scanf("%d%d%d%d", &x1, &y1, &x2, &y2); --x1;
27     s[tot].k = 2, s[tot].a = x1, s[tot].b = y1, s[tot].c = y2, s[tot].d = -1, s[tot].t = tot, s[tot++].p = cnt;
28     s[tot].k = 2, s[tot].a = x2, s[tot].b = y1, s[tot].c = y2, s[tot].d = +1, s[tot].t = tot, s[tot++].p = cnt++;
29 }
30 inline bool cmp(const data &a, const data &b) {
31     if (a.a != b.a)return a.a < b.a;
32     else return a.k < b.k;
33 }
34 void solve(int l, int r) {
35     if (l >= r)return;
36     int mid = (l + r) >> 1;
37     solve(l, mid); solve(mid + 1, r);
38     std::sort(s + l, s + r + 1, cmp);
39     for (int i = l; i <= r; ++i)
40         if (s[i].k == 1 && s[i].t <= mid)
41             add(s[i].b, s[i].c);
42         else if (s[i].k == 2 && s[i].t > mid)
43             ans[s[i].p] += ask(s[i].b, s[i].c) * s[i].d;
44     for (int i = l; i <= r; ++i)
45         if (s[i].k == 1 && s[i].t <= mid)
46             add(s[i].b, -s[i].c);
47 }
48 signed main(void) {
49     scanf("%*d%d", &w);
50     int k; while (scanf("%d", &k), k != 3)
51         (k == 1) ? add() : qry();
52     solve(1, tot - 1);
53     for (int i = 1; i < cnt; ++i)
54         printf("%d\n", ans[i]);
55 }

 

@Author: YouSiki

 

posted @ 2017-01-02 17:25  YouSiki  阅读(136)  评论(0编辑  收藏  举报