Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 12554 | Accepted: 5787 |
Description
Write a program, which receives these reports and answers queries about the current total number of active mobile phones in any rectangle-shaped area.
Input

The values will always be in range, so there is no need to check them. In particular, if A is negative, it can be assumed that it will not reduce the square value below zero. The indexing starts at 0, e.g. for a table of size 4 * 4, we have 0 <= X <= 3 and 0 <= Y <= 3.
Table size: 1 * 1 <= S * S <= 1024 * 1024
Cell value V at any time: 0 <= V <= 32767
Update amount: -32768 <= A <= 32767
No of instructions in input: 3 <= U <= 60002
Maximum number of phones in the whole table: M= 2^30
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
Source
本题需要反复修改、查询区间的值,可以考虑用线段树或树状数组,又由于所操作区间是矩阵,故用二维的;
二维树状数组的实现比二维线段树简单,且时空复杂度相同,但前者常数较小,故树状数组占优,此处不详细说明二维树状数组的原理
#include <iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include <vector>
using namespace std;
#define MY_MAX 1100
int C[MY_MAX][MY_MAX];
int Lowbit[MY_MAX];
int s;
void Add( int y, int x,int a)
{
while( y <= s )
{
int tmpx = x;
while( tmpx <= s )
{
C[y][tmpx] += a;
tmpx += Lowbit[tmpx];
}
y += Lowbit[y];
}
}
int QuerySum( int y, int x)
//查询第1行到第y行,第1列到第x列的和
{
int nSum = 0;
while( y > 0 )
{
int tmpx = x;
while( tmpx > 0)
{
nSum += C[y][tmpx];
tmpx -= Lowbit[tmpx];
}
y -= Lowbit[y];
}
return nSum;
}
int main()
{
int cmd; int x,y,a,l,b,r,t;
int i,j,k;
int n1,n2;
for( i = 1;i <= MY_MAX;i ++ )
Lowbit[i] = i & ( i ^(i - 1));
while( true)
{
scanf("%d",&cmd);
switch( cmd)
{
case 0:
scanf("%d",& s);
memset( C,0,sizeof(C));
break;
case 1:
scanf("%d%d%d",&x ,&y,&a);
Add( y + 1, x + 1, a);
break;
case 2:
scanf("%d%d%d%d",&l , &b, &r,&t);
int n1,n2,n3,n4;
l ++; b++; r ++; t ++;
//输出小矩形内的元素和
printf("%d\n",QuerySum(t,r) +QuerySum(b-1,l-1) - QuerySum(t,l-1) - QuerySum(b-1,r));
break;
case 3: return 0;
}
}
}