1. 程式人生 > >bzoj 1176 [Balkan2007]Mokia - CDQ分治 - 樹狀數組

bzoj 1176 [Balkan2007]Mokia - CDQ分治 - 樹狀數組

ica blog endif def margin 不想 sum lean add

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範圍


  題目大意 (數據結構題題面太簡潔不需要大意)

  顯然樹套樹加動態開點可以過掉這道題,然而表示並不想寫。

  由於支持離線可以考慮CDQ分治。

  首先對於一個左上角在(1, 1),右下角在(x, y)的矩陣的權值和,是可以求出來的。首先以x為第一關鍵字,y為第二關鍵字,opt為第三關鍵字排序,然後用樹狀數組維護y = i上的和。

  所以我們將一個詢問拆成4個詢問,再根據簡單容斥計算出。

Code

  1 /**
  2  * bzoj
  3  * Problem#1176
  4  * Accepted
  5  * Time:6964ms
  6  * Memory:33940k
  7  */
  8 #include <bits/stdc++.h>
  9 using namespace std;
 10 typedef bool boolean;
 11 #ifndef WIN32
 12 #define Auto "%lld"
 13 #else
 14 #define Auto "%I64d"
 15 #endif
 16
17 #define lowbit(x) (x) & (-x) 18 #define LL long long 19 20 typedef class IndexedTree { 21 public: 22 int s; 23 LL *lis; 24 25 IndexedTree() { } 26 IndexedTree(int s):s(s) { 27 lis = new LL[(s + 1)]; 28 memset(lis, 0, sizeof(LL) * (s + 1)); 29 } 30 31 inline void add(int idx, int x) { 32 for(; idx <= s; idx += lowbit(idx)) 33 lis[idx] += x; 34 } 35 36 inline LL getSum(int idx) { 37 LL ret = 0; 38 for(; idx; idx -= lowbit(idx)) 39 ret += lis[idx]; 40 return ret; 41 } 42 }IndexedTree; 43 44 typedef class Query { 45 public: 46 int x; 47 int y; 48 int opt; 49 int sign; 50 int id; 51 52 Query(int x = 0, int y = 0, int opt = 0, int sign = 0, int id = 0):x(x), y(y), opt(opt), sign(sign), id(id) { } 53 54 boolean operator < (Query b) const { 55 if(x != b.x) return x < b.x; 56 if(y != b.y) return y < b.y; 57 return opt < b.opt; 58 } 59 }Query; 60 61 int s, w; 62 int cnt = 0; 63 IndexedTree it; 64 vector<Query> qs; 65 vector<Query> bq; 66 LL *res; 67 68 inline void init() { 69 int opt, x0, y0, x1, y1, c; 70 scanf("%d%d", &s, &w); 71 while(~scanf("%d", &opt) && opt != 3) { 72 scanf("%d%d", &x0, &y0); 73 if(opt == 1) { 74 scanf("%d", &c); 75 qs.push_back(Query(x0, y0, opt, c, cnt)); 76 } else { 77 scanf("%d%d", &x1, &y1); 78 qs.push_back(Query(x1, y1, opt, 1, cnt)); 79 qs.push_back(Query(x0 - 1, y1, opt, -1, cnt)); 80 qs.push_back(Query(x1, y0 - 1, opt, -1, cnt)); 81 qs.push_back(Query(x0 - 1, y0 - 1, opt, 1, cnt)); 82 bq.push_back(Query(x0, y0, x1, y1, cnt)); 83 } 84 cnt++; 85 } 86 } 87 88 void CDQDividing(int l, int r, vector<Query> &que) { 89 if(que.empty()) return; 90 if(l == r) return; 91 92 int mid = (l + r) >> 1; 93 for(int i = 0; i < (signed)que.size(); i++) { 94 if(que[i].opt == 1 && que[i].id <= mid) 95 it.add(que[i].y, que[i].sign); 96 if(que[i].opt == 2 && que[i].id > mid) 97 res[que[i].id] += it.getSum(que[i].y) * que[i].sign; 98 } 99 100 for(int i = 0; i < (signed)que.size(); i++) 101 if(que[i].opt == 1 && que[i].id <= mid) 102 it.add(que[i].y, -que[i].sign); 103 104 vector<Query> ql, qr; 105 for(int i = 0; i < (signed)que.size(); i++) 106 if(que[i].id <= mid) 107 ql.push_back(que[i]); 108 else 109 qr.push_back(que[i]); 110 111 que.clear(); 112 CDQDividing(l, mid, ql); 113 CDQDividing(mid + 1, r, qr); 114 } 115 116 inline void solve() { 117 res = new LL[(cnt + 1)]; 118 memset(res, 0, sizeof(LL) * (cnt + 1)); 119 sort(qs.begin(), qs.end()); 120 it = IndexedTree(w); 121 CDQDividing(0, cnt - 1, qs); 122 123 for(int i = 0; i < (signed)bq.size(); i++) 124 printf(Auto"\n", res[bq[i].id] + (bq[i].opt - bq[i].x + 1) * (bq[i].sign - bq[i].y + 1) * s); 125 } 126 127 int main() { 128 init(); 129 solve(); 130 return 0; 131 }

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範圍

bzoj 1176 [Balkan2007]Mokia - CDQ分治 - 樹狀數組