线段树(模板)

一个经典问题

已知一组数,有两种操作:

第一个是修改,将第i个数变成另一个数;

第二个是在查询,求[a,b]区间所有值的总和;

例子:

5 3

1

2

3

4

2

2 3 4

2 4 5

1 2  4


10

当有不大于100000个数和不大于100000个询问怎么办,难道o(n*q)?不,看程序吧!!

程序:

type arr=record
           lc:longint;【左孩子】
           rc:longint;【右孩子】
         end;
var
  a:array[1..100000]of longint;
  b:array[1..100000*4]of arr;
  sum,max:array[1..100000*4]of longint; 【数的结点数小于等于一组数的个数*4】
  n,m,i,j,a1,a2,a3:longint;
procedure jian(l,r,k:longint);【建立线段树】
var
  mid:longint;
begin
  if l=r then begin sum[k]:=a[l];exit; end;

  mid:=(l+r) div 2;
  b[k*2].lc:=l;b[k*2].rc:=mid;
  b[k*2+1].lc:=mid+1;b[k*2+1].rc:=r;

  jian(l,mid,k*2);
  jian(mid+1,r,k*2+1);

  sum[k]:=sum[k*2]+sum[k*2+1];
end;

树的样子:

                              [1,5]
   
   [1,3]              [4,5]
         
    [1,2]   [3,3]     [4,4]   [5,5]

        [1,1]   [2,2]            

[1,5]为一区间,[1,3]为一区间,。。。

              
function cha(l,r,k:longint):longint;
var
  mid:longint;
begin
  mid:=(b[k].lc+b[k].rc) div 2;cha:=0;
  if (l=b[k].lc)and(r=b[k].rc) then exit(sum[k]);
  if (l<=mid)and(r<=mid) then cha:=cha+cha(l,r,k*2);
  if (l<=mid)and(r>mid) then cha:=cha+cha(l,mid,k*2)+cha(mid+1,r,k*2+1);
  if (l>mid)and(r>mid) then cha:=cha+cha(l,r,k*2+1);
  [此区间要么都在左边,要么都在右边,要么一边有一点]
end;

procedure d(wei,p,k:longint);
var
  mid:longint;
begin
  if (b[k].lc=b[k].rc)and(b[k].lc=wei) then
    begin
      sum[k]:=p;
      max[k]:=p;
      exit;
    end;
  sum[k]:=sum[k*2]+sum[k*2+1];
  mid:=(b[k].lc+b[k].rc) div 2;
  if wei<=mid then d(wei,p,k*2) else d(wei,p,k*2+1);
end;
begin
  readln(n,m);[n个数,m个询问]
  for i:=1 to n do readln(a[i]);
  b[1].lc:=1;b[1].rc:=n;
  jian(1,n,1);
  for i:=1 to m do
    begin
      readln(a1,a2,a3);
      if a1=1 then
        begin
          write(cha(a2,a3,1));
        end
      else if a1=2 then d(a2,a3,1);
    end;
end.

回头写个树状数组的,当然树状数组代码很少,却没有线段树实用,建议线段树,树状数组做备用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值