# Population zoj 3018

Population
Time Limit: 10000 msMemory Limit: 32768 KB
It is always exciting to see people settling in a new continent. As the head of the population management office, you are supposed to know, at any time, how people are distributed in this continent.

The continent is divided into square regions, each has a center with integer coordinates (x, y). Hence all the people coming into that region are considered to be settled at the center position. Given the positions of the corners of a rectangle region, you are supposed to count the number of people living in that region.

Input

Your program must read inputs from the standard input. Since there are up to 32768 different regions and possibly even more queries, please use "scanf" and "printf" instead of "cin" and "cout" to avoid timeout.

The character "I" in a line signals the coming in of new groups of people. In the following lines, each line contains three integers: X, Y, and N, where X and Y (1 <= X, Y <= 20000) are the coordinates of the region's center, and N (1 <= N <= 10000) is the number of people coming in.

The character "Q" in a line signals the query of population. The following lines each contains four numbers: Xmin, Xmax, Ymin, Ymax, where (Xmin, Ymin) and (Xmax, Ymax) are the integer coordinates of the lower left corner and the upper right corner of the rectangle, respectively.

The character "E" signals the end of a test case. Process to the end of file.

Output

For each "Q" case, print to the standard output in a line the population in the given rectangle region. That is, you are supposed to count the number of people living at all the positions (x, y) such that Xmin <= x <= Xmax, and Ymin <= y <= Ymax.

Sample Input

I
8 20 1
4 5 1
10 11 1
12 10 1
18 14 1
Q
8 10 5 15
8 20 10 14
I
7 6 1
10 3 2
7 2 1
2 3 2
10 3 1
Q
2 20 2 20
E
Sample Output

1
3
12

[思路]：求的是一个二维区间之间的和

#include <bits/stdc++.h>
using namespace std;
/**
* 面积树
* 四叉树
* **/
typedef long long LL;
int str_to_int(string a){
int sum = 0;
for(int i = 0; i < a.length(); i ++){
sum = sum * 10 + (a[i] - '0');
}
return sum;
}
int tot = 0;
const int MAXN = 1e7 + 5;
struct AREA_tree{
struct NODE{
int lx, ly, rx, ry;///左下角 右上角
LL sum;///区间的总和
int son[4];///儿子节点对应的是点在数组中的编号
/*划分为四个部分，四个儿子节点对应四个部分
0 <xmid + 1, ymid + 1> <rx, ry>
1 <lx, ymid + 1> <xmid, ry>
2 <lx, ly> <xmid, ymid>
3 <xmid + 1, ly> <rx, ymid>
*/
}tree[MAXN];
void Init_NODE(NODE &x){
for(int i = 0; i < 4; i ++){
x.son[i] = -1;
}///清空儿子节点，代表没有下一个区间
}
void Init(){
tot = 0;///初始化为0
}
int add(int lx, int ly, int rx, int ry){///添加一个<lx, ly> <rx, ry>的节点
tree[tot].lx = lx, tree[tot].rx = rx, tree[tot].ly = ly, tree[tot].ry = ry;
Init_NODE(tree[tot]);
tree[tot].sum = 0;
}
void update(int root, int x, int y, int value){///更新一个节点
if(tree[root].lx == tree[root].rx && tree[root].ly == tree[root].ry){
tree[root].sum += value;///如果跑到单点上，那么更新总和
return ;
}
int xmid = (tree[root].lx + tree[root].rx) >> 1;///xmid
int ymid = (tree[root].ly + tree[root].ry) >> 1;///ymid
/*
0 <xmid + 1, ymid + 1> <rx, ry>
1 <lx, ymid + 1> <xmid, ry>
2 <lx, ly> <xmid, ymid>
3 <xmid + 1, ly> <rx, ymid>
*/
int rx, ry, lx, ly;
rx = tree[root].rx, ry = tree[root].ry, lx = tree[root].lx, ly = tree[root].ly;
///判断更新的区间在哪个子区间
if(x <= rx && y <= ry && x >= xmid + 1 && y >= ymid + 1){
if(tree[root].son[0] == -1){///右上
tree[root].son[0] = add(xmid + 1, ymid + 1, rx, ry);
}
update(tree[root].son[0], x, y, value);
}
else if(x <= xmid && y <= ry && x >= lx && y >= ymid + 1){///左上
if(tree[root].son[1] == -1){
tree[root].son[1] = add(lx, ymid + 1, xmid, ry);
}
update(tree[root].son[1], x, y, value);
}
else if(x <= xmid && y <= ymid && x >= lx && y >= ly){///左下
if(tree[root].son[2] == -1){
tree[root].son[2] = add(lx, ly, xmid, ymid);
}
update(tree[root].son[2], x, y, value);
}
else if(x <= rx && y <= ymid && x >= xmid + 1 && y >= ly){///右下
if(tree[root].son[3] == -1){
tree[root].son[3] = add(xmid + 1, ly, rx, ymid);
}
update(tree[root].son[3], x, y, value);
}
int sum = 0;
for(int i = 0; i < 4; i ++){
if(tree[root].son[i] != -1){
sum += tree[tree[root].son[i]].sum;
}
}///更新相当于线段树的push_up
tree[root].sum = sum;
return ;
}
LL query(int root, int xmin, int ymin, int xmax, int ymax){
if(tree[root].lx >= xmin && tree[root].ly >= ymin && tree[root].rx <= xmax && tree[root].ry <= ymax){
return tree[root].sum;
}
int xmid = (tree[root].lx + tree[root].rx) >> 1;
int ymid = (tree[root].ly + tree[root].ry) >> 1;
/*
0 <xmid + 1, ymid + 1> <rx, ry>
1 <lx, ymid + 1> <xmid, ry>
2 <lx, ly> <xmid, ymid>
3 <xmid + 1, ly> <rx, ymid>
查询语句，依旧是查询四个区间
判断是否应该查询这个区间
或者时对应的区间被包含
*/
int rx, ry, lx, ly;
rx = tree[root].rx, ry = tree[root].ry, lx = tree[root].lx, ly = tree[root].ly;
LL re = 0;
if(xmin <= xmid && ymin <= ymid){
if(tree[root].son[2] != -1)
re += query(tree[root].son[2], xmin, ymin, xmax, ymax);
}
if(xmax > xmid && ymin <= ymid){
if(tree[root].son[3] != -1)
re += query(tree[root].son[3], xmin, ymin, xmax, ymax);
}
if(xmin <= xmid && ymax > ymid){
if(tree[root].son[1] != -1)
re += query(tree[root].son[1], xmin, ymin, xmax, ymax);
}
if(xmax > xmid && ymax > ymid){
if(tree[root].son[0] != -1)
re += query(tree[root].son[0], xmin, ymin, xmax, ymax);
}
return re;
}
}area_tree;
int main(){
#ifdef moxin
freopen("C:\\Users\\user\\Desktop\\dp_data\\1.in", "r", stdin);
freopen("C:\\Users\\user\\Desktop\\dp_data\\1.out", "w", stdout);
#endif
ios::sync_with_stdio(false);
string str;
int flag = 0;///0 - I 1 - Q
area_tree.Init();
while(cin >> str){
if(str[0] == 'E'){
area_tree.Init();
continue;
}
if(str[0] == 'I') {
flag = 0; continue;
}
if(str[0] == 'Q') {
flag = 1; continue;
}
if(flag == 0){
int x = str_to_int(str);
int y, z;
cin >> y >> z;
area_tree.update(0, x, y, z);
}
else if(flag == 1){
int x1, y1, x2, y2;
x1 = str_to_int(str);
cin >> x2 >> y1 >> y2;
cout << area_tree.query(0, x1, y1, x2, y2) << endl;
}
}
return 0;
}

07-14 2617
09-13 1653
02-01 80
08-28 563
01-22 88
10-03 362
08-13 69
11-10 779
08-23 40
08-08 377
03-02 1250
08-24 355
07-21 213
04-05 77