线段树模板(以求和为例)
单点更新,区间查询


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.
区间更新,区间查询


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.
构造


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;
修改单点,查询区间


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;
修改区间,查询区间


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;