题目链接:https://vjudge.net/problem/POJ-1195
有一个正方形区域S*S(1<=S<=1024)。含有很多小区域,小区域编号从0开始,直到S-1。每一个单位各是一个区域,每个区域上有一定数量的手机,同时每一个区域上的手机的数目也是不断变化的,现在要一边进行修改某些单位格子内的手机的数目,同时也要询问某些区域的手机数目。 数据保证每个格子内手机数目一直在int范围内,查询的区域内的手机数目也在int范围内
Input
有多组数据,每一行先输入一个数字x,如果x=0再输入S,表示区域的大小,并且所有的区域内都没有手机:如果x=1,接着输入x,y,a,表示坐标(x,y)的这个小格内增加a个手机:如果x=2,接着输入x1,y1,x2,y2.表示要查询的矩形区域的左上角坐标和右下角坐标,如果x=3,程序结束。
Output
对于每次查询,输出这个区域内的手机数目。
Sample Input
0 4 1 1 2 3 2 0 0 2 2 1 1 1 2 1 1 2 -1 2 1 1 2 3 3
Sample Output
3 4
线段树:4倍的开不了,开3倍就好
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
#define lowbit(x) (x & (-x))
#define INF 0x3f3f3f3f
const int N = 1055;
int n, m;
int sum[N * 3][N * 3];
void updatey(int y, int l, int r, int cur, int p, int op, int val) {
if(l == r) {
if(op == 1) sum[p][cur] += val;
else sum[p][cur] = sum[p << 1][cur] + sum[p << 1 | 1][cur];
return;
}
int mid = (r + l) >> 1;
if(y <= mid)updatey(y, l, mid, cur << 1, p, op, val);
else updatey(y, mid + 1, r, cur << 1 | 1, p, op, val);
sum[p][cur] = sum[p][cur << 1] + sum[p][cur << 1 | 1];
}
void updatex(int x, int y, int l, int r, int cur, int val) {
if(l == r) {
updatey(y, 1, n, 1, cur, 1, val);
return;
}
int mid = (l + r) >> 1;
if(x <= mid) updatex(x, y, l, mid, cur << 1, val);
else updatex(x, y, mid + 1, r, cur << 1 | 1, val);
updatey(y, 1, n, 1, cur, 2, val);
}
int queryy(int ly, int ry, int l, int r, int cur , int p) {
if(ly <= l && r <= ry) {
return sum[p][cur];
}
int res = 0;
int mid = (l + r) >> 1;
if(ly <= mid) res += queryy(ly, ry, l, mid, cur << 1, p);
if(ry > mid) res += queryy(ly, ry, mid + 1, r, cur << 1 | 1, p);
return res;
}
int queryx(int lx, int rx, int ly, int ry, int l, int r, int cur) {
int res = 0;
if(lx <= l && r <= rx) {
res = queryy(ly, ry, 1, n, 1, cur);
return res;
}
int mid = (l + r) >> 1;
if(lx <= mid) res += queryx(lx, rx, ly, ry, l, mid, cur << 1);
if(rx > mid) res += queryx(lx, rx, ly, ry, mid + 1, r, cur << 1 | 1);
return res;
}
int main() {
int T;
char op[2];
int x1, x2, y1, y2;
int val;
while(~scanf("%d", &m) && m != 3) {
if(m == 0) {
scanf("%d", &n);
n++;
memset(sum, 0, sizeof(sum));
} else if(m == 1) {
scanf("%d %d %d", &x1, &y1, &val);
x1++, y1++;
updatex(x1, y1, 1, n, 1, val);
} else {
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
x1++; x2++; y1++; y2++;
printf("%d\n", queryx(x1, x2, y1, y2, 1, n, 1));
}
}
return 0;
}
树状数组:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define lowbit(x) (x&(-x))
const int N=1305;
typedef long long ll;
int sum[N][N];
int n,m;
void add(int x,int y,int val)
{
for(int i=x;i<=n+1;i+=lowbit(i))
for(int j=y;j<=n+1;j+=lowbit(j))
sum[i][j]+=val;
}
int query(int x,int y)
{
int ans=0;
for(int i=x;i>0;i-=lowbit(i))
for(int j=y;j>0;j-=lowbit(j))
ans+=sum[i][j];
return ans;
}
int main()
{
while(~scanf("%d%d",&m,&n))
{
int op;
int l,r,val,x1,x2,y1,y2;
memset(sum,0,sizeof(sum));
while(scanf("%d",&op)&&op!=3)
{
if(op==1)
{
scanf("%d%d%d",&x1,&y1,&val);
x1++,y1++;
add(x1,y1,val);
}
else
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1++,x2++,y1++,y2++;
printf("%d\n",query(x2,y2)-query(x1-1,y2)-query(x2,y1-1)+query(x1-1,y1-1));
}
}
}
return 0;
}