线段树 例六 未解决
题目大意
在一个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.