题目大意
在一个N*N的方格中,开始每个格子里的数都是0。现在动态地提出一些问题和修改:提问的形式是求某一个特定的子矩阵(x1,y1)-(x2,y2)中所有元素的和;修改的规则是指定某一个格子(x,y),在(x,y)中的格子元素上加上或者减去一个特定的值A。现在要求你能对每个提问作出正确的回答。1≤N≤1024,提问和修改的总数可能达到60000条。
分析
我有一个超时的算法:把每一行都建一棵线段树(f[x])(x为行)(f[x]为一行的情况)
统计(x,y)(x1,y1)时把f[x]…f[x1]的线段树区间[y,y1]加在一起。
但超时。
type
pnode=^tnode;
tnode=record
lc,rc:pnode;
c:longint;
end;
var
f:array[0..1200] of pnode;
i,j,k:longint;
x,y,x1,y1:longint;
n,m:longint;
co:longint;
s:longint;
ans:longint;
procedure neww(var t:pnode);
begin
if t=nil then
begin
new(t);
t^.c:=0;
t^.lc:=nil;
t^.rc:=nil;
end;
end;
procedure insert(var t:pnode; l,r,x,y,co:longint);
var
i,j,k:longint;
mid:longint;
begin
with t^ do
begin
{if c=0 then
begin }
c:=c+co;
mid:=(l+r) div 2;
if (l=x) and (r=y)
then
exit;
if (l<=x) and (mid>=y)
then
begin
neww(lc);
insert(lc,l,mid,x,y,co);
exit;
end;
if (mid<x) and (r>=y)
then
begin
neww(rc);
insert(rc,mid+1,r,x,y,co);
exit;
end;
neww(lc);
neww(rc);
insert(lc,l,mid,x,mid,co);
insert(rc,mid+1,r,mid+1,y,co);
end;
{end;}
end;
function find(t:pnode;l,r,x,y:longint):longint;
var
mid:longint;
begin
if t=nil then exit(0);
with t^ do
begin
mid:=(l+r) div 2;
if (l=x) and (r=y)
then
begin
find:=c;
exit;
end;
if (l<=x) and (mid>=y)
then
begin
find:=find(lc,l,mid,x,y);
exit;
end;
if (mid<x) and (r>=y)
then
begin
find:=find(rc,mid+1,r,x,y);
exit;
end;
find:=find(lc,l,mid,x,mid)+find(rc,mid+1,r,mid+1,y);
end;
end;
begin
readln(i,m);
m:=m-1;
while not eof do
begin
read(s);
if s>=3 then break;
if s=1
then
begin
readln(x,y,co);
neww(f[x]);
insert(f[x],0,m,y,y,co);
end
else
begin
readln(x,y,x1,y1);
ans:=0;
for i:=x to x1 do
begin
neww(f[i]);
ans:=ans+find(f[i],0,m,y,y1);
end;
writeln(ans);
end;
end;
end.