1176: [Balkan2007]Mokia
Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 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
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范围
Source
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 ", ans[i]); 55 }
@Author: YouSiki