线段树与树状数组模板

线段树模板(以求和为例)

单点更新,区间查询

program stree1;
var
  dat:array[0..400000]of longint;
  n,i,m,len,x,y,v:longint;
function min(x,y:longint):longint;
begin
  if x<y then min:=x else min:=y;
end;
function max(x,y:longint):longint;
begin
  if x>y then max:=x else max:=y;
end;
procedure build(n:longint);
var i:longint;
begin
  len:=1; while len<n do len:=len*2;
  for i:=0 to 2*len-1 do dat[i]:=0;
end;
procedure put(k,v:longint);
begin
  k:=k+len-1; inc(dat[k],v);
  while k>0 do
   begin
    k:=(k-1) div 2; dat[k]:=dat[k*2+1]+dat[k*2+2];
   end;
end;
function query(k,a,b,l,r:longint):longint;
var sum,mid:longint;
begin
  if (b<=l)or(r<=a) then exit(0)
  else  if (a<=l)and(r<=b) then exit(dat[k])
  else
  begin
    sum:=0;  mid:=(l+r) div 2;
    inc(sum,query(k*2+1,a,b,l,mid)); inc(sum,query(k*2+2,a,b,mid,r));
    exit(sum);
  end;
end;
begin
  readln(n); build(n);
  for i:=1 to n do
   begin
     readln(x); put(i,x);
   end;
  readln(m);
  for i:=1 to m do
   begin
     readln(x,y,v);
     if x=1 then put(y,v) else writeln(query(0,y,v+1,0,len));
   end;
end.
View Code

区间更新,区间查询

program stree2;
var
  data,datb:array[0..8000000]of int64;
  n,i,m,len,x,y,z:longint;
  v:int64;
function min(x,y:longint):longint;
begin
  if x<y then min:=x else min:=y;
end;
function max(x,y:longint):longint;
begin
  if x>y then max:=x else max:=y;
end;
procedure build(n:longint);
var i:longint;
begin
  len:=1; while len<n do len:=len*2;
  for i:=0 to 2*len-1 do begin data[i]:=0;datb[i]:=0; end;
end;
procedure change(k,a,b,l,r:longint; v:int64);
var mid:longint;
begin
  if (a<=l)and(r<=b) then inc(data[k],v)
   else if (l<b)and(a<r) then
   begin
     inc(datb[k],(min(b,r)-max(a,l))*v);  mid:=(l+r) div 2;
     change(k*2+1,a,b,l,mid,v); change(k*2+2,a,b,mid,r,v);
   end;
end;
function query(k,a,b,l,r:longint):int64;
var  sum:int64; mid:longint;
begin
  if (b<=l)or(r<=a) then exit(0)
   else if (a<=l)and(r<=b) then exit(data[k]*(r-l)+datb[k])
    else
     begin
      sum:=(min(b,r)-max(a,l))*data[k];mid:=(l+r) div 2;
      inc(sum,query(k*2+1,a,b,l,mid)); inc(sum,query(k*2+2,a,b,mid,r));
      exit(sum);
     end;
end;
begin
  readln(n); build(n);
  for i:=1 to n do
   begin
     read(x); change(0,i,i+1,0,len,x);
   end;
  readln(m);
  for i:=1 to m do
   begin
     read(x,y,z);
     if x=1 then begin read(v);change(0,y,z+1,0,len,v); end else writeln(query(0,y,z+1,0,len));
   end;
end.
View Code

构造

procedure make(p,l,r:longint);
var mid:longint;
begin
  a[p,1]:=l; a[p,2]:=r; a[p,3]:=0; a[p,4]:=0;if l=r then a[p,3]:=w[l];
  if l<r then
   begin
     mid:=(l+r) div 2;
     make(p*2,l,mid); make(p*2+1,mid+1,r);
     a[p,3]:=a[p*2,3]+a[p*2+1,3];
   end;
end; 
View Code1

修改单点,查询区间

procedure change1(p,x,num:longint);
var mid:longint;
begin
  if a[p,1]=a[p,2] then inc(a[p,3],num)
  else
    begin
      mid:=(a[p,1]+a[p,2]) div 2;
      if x<=mid then change1(p*2,x,num) else if x>mid then change1(p*2+1,x,num);
      a[p,3]:=a[p*2,3]+a[p*2+1,3];
    end;
end;
function  query1(p,l,r:longint):int64;
var mid:longint;  ans:int64;
begin
  if (l<=a[p,1])and(a[p,2]<=r) then exit(a[p,3])
 else
  begin
    mid:=(a[p,1]+a[p,2]) div 2; ans:=0;
    if l<=mid then inc(ans,query1(p*2,l,r));
    if r>mid then inc(ans,query1(p*2+1,l,r));
    exit(ans);
  end;
end;
View Code2

修改区间,查询区间 

procedure update(p:longint);
begin
  inc(a[p*2,3],a[p,4]*(a[p*2,2]-a[p*2,1]+1));
  inc(a[p*2+1,3],a[p,4]*(a[p*2+1,2]-a[p*2+1,1]+1));
  inc(a[p*2,4],a[p,4]); inc(a[p*2+1,4],a[p,4]); a[p,4]:=0;
end;
procedure change2(p,l,r,num:longint);
var mid:longint;
begin
  if (l<=a[p,1])and(a[p,2]<=r) then
   begin
     a[p,3]:=a[p,3]+num*(a[p,2]-a[p,1]+1); a[p,4]:=a[p,4]+num;
   end
  else
   begin
     if a[p,4]>0 then update(p);mid:=(a[p,1]+a[p,2]) div 2;
     if l<=mid then change2(p*2,l,r,num);
     if r>mid then change2(p*2+1,l,r,num);
     a[p,3]:=a[p*2,3]+a[p*2+1,3];
   end;
end;
function query3(p,l,r:longint):int64;
var mid:longint; ans:int64;
begin
  if (l<=a[p,1])and(a[p,2]<=r) then exit(a[p,3])
  else
    begin
      if a[p,4]>0 then update(p);
      ans:=0; mid:=(a[p,1]+a[p,2]) div 2;
      if l<=mid then inc(ans,query3(p*2,l,r));
      if r>mid then inc(ans,query3(p*2+1,l,r));
      exit(ans);
    end;
end;           
View Code4

 

转载于:https://www.cnblogs.com/qtyytq/p/4645758.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值