题目大意
一行N个方格,开始每个格子里的数都是0。现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和;修改的规则是指定某一个格子x,加上或者减去一个特定的值A。现在要求你能对每个提问作出正确的回答。
分析
方法一:线段树
为线段树每个节点增加一个Count域。表示所对应区间内元素之和。每次修改一个格子,需要修改从叶结点到根结点路径上所有结点的值。
所以统计算法时,要用和插入算法一样的二分法:使得可以把所有的要加的区间找出来。
注意,目中的区间是以元素为端点,因此[a,b]和[b,c]存在重合。具体见代码:
type
pnode=^tnode;
tnode=record
lc,rc:pnode;
c:longint;
end;
var
t:pnode;
i,j,k:longint;
x,y:longint;
n,m:longint;
co:longint;
s:char;
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(m);
readln(n);
fillchar(t,sizeof(t),0);
neww(t);
for i:=1 to n do
begin
readln(s,x,co);
if s='M' then insert(t,1,m,x,x,co)
else write(find(t,1,m,x,co));
end;
end.
方法二:树状数组
var
n,m:longint;
a,b:array[0..40000] of longint;
i,j,k:longint;
x,y:longint;
s:char;
procedure bian(p,c:longint);
begin
while p<=m do
begin
b[p]:=b[p]+c;
p:=p+(p and (p xor (p-1)));
end;
end;
function tong(p:longint):longint;
begin
tong:=0;
while p>0 do
begin
tong:=tong+b[p];
p:=p-(p and (p xor (p-1)));
end;
end;
begin
readln(m);
readln(n);
j:=0;
for i:=1 to n do
begin
readln(s,x,y);
if s='M' then bian(x,y)
else writeln(tong(y)-tong(x-1));
end;
end.