【BZOJ2683】简单题 [分治][树状数组]

简单题

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

 

posted @ 2017-11-07 20:10  BearChild  阅读(266)  评论(0编辑  收藏  举报