1. 程式人生 > >【BZOJ2683】簡單題 [分治][樹狀數組]

【BZOJ2683】簡單題 [分治][樹狀數組]

math 所有 操作數 def 正整數 || lap ref 維護

簡單題

Time Limit: 50 Sec Memory Limit: 128 MB
[Submit][Status][Discuss]

Description

  你有一個N*N的棋盤,每個格子內有一個整數,初始時的時候全部為0,現在需要維護兩種操作:

命令

參數限制

內容

1 x y A

1<=x,y<=N,A是正整數

將格子x,y裏的數字加上A

2 x1 y1 x2 y2

1<=x1<= x2<=N

1<=y1<= y2<=N

輸出x1 y1 x2 y2這個矩形內的數字和

3

終止程序

Input

  輸入文件第一行一個正整數N。   接下來每行一個操作。

Output

  對於每個2操作,輸出一個對應的答案。

Sample Input

  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

  1<=N<=500000,操作數不超過200000個,內存限制20M。   對於100%的數據,操作1中的A不超過2000。

Solution

  首先把詢問拆成4個,那麽我們就只要維護一個點左下角權值和

了。

  然後對所有操作按照 x 升序排序。

  對 y 用個樹狀數組前綴和,(由於 x 升序,所以此時詢問已經相當於對y求前綴和了)

  以mid為分界線,考慮左區間對右區間的影響

  顯然,我們可以把左區間的修改執行,然後執行右區間的詢問

  這樣我們就做完了這道題。

Code

技術分享
  1 #include<iostream>
  2 #include<string>
  3 #include<algorithm>
  4 #include<cstdio>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cmath>
  8 using namespace std;
  9 typedef long long s64;
 10  
 11 const int ONE = 1000005;
 12 const int INF = 214748340;
 13  
 14 int get()
 15 {
 16         int res = 1, Q = 1; char c;
 17         while( (c = getchar()) < 48 || c > 57)
 18             if(c == -) Q = -1;
 19         if(Q) res = c - 48;
 20         while( (c = getchar()) >= 48 && c <= 57)
 21             res = res * 10 + c - 48;
 22         return res * Q;
 23 }
 24  
 25 int n;
 26 namespace BIT
 27 {
 28         int C[ONE];
 29         int lowbit(int i) {return i & -i;}
 30         void Add(int R, int x)
 31         {
 32             for(int i = R; i <= n; i += lowbit(i))
 33                 C[i] += x;
 34         }
 35         int Query(int R)
 36         {
 37             int res = 0;
 38             for(int i = R; i >= 1; i -= lowbit(i))
 39                 res += C[i];
 40             return res;
 41         }
 42 }
 43  
 44 int id, query_num, Ans[ONE];
 45 struct power
 46 {
 47         int id, opt, from;
 48         int x, y, val;
 49 }oper[ONE], q[ONE];
 50  
 51 bool cmp(const power &a, const power &b)
 52 {
 53         if(a.x != b.x) return a.x < b.x;
 54         return a.opt < b.opt;
 55 }
 56  
 57 void Deal(int x_1, int y_1, int x_2, int y_2)
 58 {
 59         query_num++;
 60         oper[++id] = (power){id, 2, query_num, x_2, y_2, 1};
 61         oper[++id] = (power){id, 2, query_num, x_1 - 1, y_1 - 1, 1};
 62         oper[++id] = (power){id, 2, query_num, x_1 - 1, y_2, -1};
 63         oper[++id] = (power){id, 2, query_num, x_2, y_1 - 1, -1};
 64 }
 65  
 66 void Solve(int l, int r)
 67 {
 68         if(l >= r) return;
 69          
 70         int mid = l + r >> 1;
 71         for(int i = l; i <= r; i++)
 72         {
 73             if(oper[i].opt == 1 && oper[i].id <= mid)
 74                 BIT::Add(oper[i].y, oper[i].val);
 75             if(oper[i].opt == 2 && oper[i].id > mid)
 76                 Ans[oper[i].from] += BIT::Query(oper[i].y) * oper[i].val;
 77         }
 78          
 79         for(int i = l; i <= r; i++)
 80             if(oper[i].opt == 1 && oper[i].id <= mid)
 81                 BIT::Add(oper[i].y, -oper[i].val);
 82          
 83         int tl = l, tr = mid + 1;
 84         for(int i = l; i <= r; i++)
 85             if(oper[i].id <= mid) q[tl++] = oper[i];
 86             else q[tr++] = oper[i];
 87          
 88         for(int i = l; i <= r; i++)
 89             oper[i] = q[i];
 90          
 91         Solve(l, mid), Solve(mid + 1, r);
 92 }
 93  
 94 int opt, x_1, y_1, x_2, y_2;
 95  
 96 int main()
 97 {
 98         n = get();
 99         for(;;)
100         {
101             opt = get();
102             if(opt == 3) break;
103             if(opt == 1)
104                 oper[++id].id = id, oper[id].opt = 1,
105                 oper[id].x = get(), oper[id].y = get(), oper[id].val = get();
106             if(opt == 2)
107                 x_1 = get(), y_1 = get(),
108                 x_2 = get(), y_2 = get(),
109                 Deal(x_1, y_1, x_2, y_2);
110         }
111          
112         sort(oper + 1, oper + id + 1, cmp);
113          
114         Solve(1, id);
115          
116         for(int i = 1; i <= query_num; i++)
117             printf("%d\n", Ans[i]);
118 }
View Code

【BZOJ2683】簡單題 [分治][樹狀數組]