原始线段树


原始线段树模板:

program fjsd;
var
  i,j,d,ll,rr,x,n,m,t:longint;
  l,r,lson,rson,sum,max,sign,a:array[0..100000] of longint;

procedure build(i,ll,rr:longint);
var
  mid:longint;
begin
  l[i]:=ll;r[i]:=rr;
  if ll<rr then
  begin
    mid:=(ll+rr) div 2;
    inc(t);lson[i]:=t;inc(t);rson[i]:=t;
    build(lson[i],ll,mid); build(rson[i],mid+1,rr);
    if max[lson[i]]>max[rson[i]] then max[i]:=max[lson[i]]
    else max[i]:=max[rson[i]];
    sum[i]:=sum[lson[i]]+sum[rson[i]];
  end
  else begin
    sum[i]:=a[ll];
    max[i]:=a[ll];
  end;
end;

procedure relax(x:longint);
begin
  if sign[x]<>0 then
  begin
    inc(max[x],sign[x]);
    inc(sum[x],sign[x]*(r[x]-l[x]+1));
    if lson[x]<>0 then inc(sign[lson[x]],sign[x]);
    if rson[x]<>0 then inc(sign[rson[x]],sign[x]);
    sign[x]:=0;
  end;
end;

procedure add(x,ll,rr,d:longint);
var
  mid:longint;
begin
  relax(x);
  if (ll<=l[x])and(r[x]<=rr) then
  begin
    inc(sign[x],d);
    exit;
  end;
  mid:=(l[x]+r[x]) div 2;
  if ll<=mid then add(lson[x],ll,rr,d);
  if rr>mid then add(rson[x],ll,rr,d);
  if sign[lson[x]]<>0 then relax(lson[x]);
  if sign[rson[x]]<>0 then relax(rson[x]);
  sum[x]:=sum[lson[x]]+sum[rson[x]];
  if max[lson[x]]>max[rson[x]] then max[x]:=max[lson[x]]
  else max[x]:=max[rson[x]];
end;

function getsum(x,ll,rr:longint):longint;
var
  mid:longint;
begin
  relax(x); getsum:=0;
  if (ll<=l[x])and(r[x]<=rr) then exit(sum[x]);
  mid:=(l[x]+r[x]) div 2;
  if ll<=mid then inc(getsum,getsum(lson[x],ll,rr));
  if rr>mid then inc(getsum,getsum(rson[x],ll,rr));
end;

function getmax(x,ll,rr:longint):longint;
var
  mid,tmp:longint;
begin
  relax(x); getmax:=0;
  if (ll<=l[x])and(r[x]<=rr) then exit(max[x]);
  mid:=(l[x]+r[x]) div 2;
  if ll<=mid then
  begin
    tmp:=getmax(lson[x],ll,rr);
    if tmp>getmax then getmax:=tmp;
  end;
  if rr>mid then
  begin
    tmp:=getmax(rson[x],ll,rr);
    if tmp>getmax then getmax:=tmp;
  end;
end;

Begin
  assign(input,'segment.in');reset(input);
  assign(output,'segment.out');rewrite(output);
  readln(n);
  for i:=1 to n do read(a[i]);
  t:=1;
  build(1,1,n);
  readln(m);
  for i:=1 to m do
  begin
    read(x);
    if x=0 then begin
      readln(ll,rr,d);
      add(1,ll,rr,d);
    end
    else if x=1 then begin
      readln(ll,rr);
      writeln(getsum(1,ll,rr));
    end
    else begin
      readln(ll,rr);
      writeln(getmax(1,ll,rr));
    end;
  end;
  close(input);close(output);
End.                



某道poj的题

program fjsd;
var
  i,j,n,t,o,len,ans,ll,rr,cc:longint;
  l,r,ls,rs,c,sign:array[0..100000] of longint;
  b:array[0..30] of boolean;
  ch:char;


procedure build(x,ll,rr:longint);
var
  mid:longint;
begin
  l[x]:=ll;r[x]:=rr;
  if ll<rr then
  begin
    mid:=(ll+rr)div 2;
    inc(t,2);
    ls[x]:=t-1;rs[x]:=t;
    build(t-1,ll,mid);build(t,mid+1,rr);
  end;
end;


procedure relax(x:longint);
begin
  if sign[x]<>0 then
  begin
    sign[ls[x]]:=sign[x];
    sign[rs[x]]:=sign[x];
    c[x]:=sign[x];
    sign[x]:=0;
  end;
end;


procedure modify(x,ll,rr,cc:longint);
var
  mid:longint;
begin
  relax(x);
  if (ll<=l[x])and(r[x]<=rr) then
  begin
    sign[x]:=cc;
    exit;
  end;
  mid:=(l[x]+r[x])div 2;
  if ll<=mid then modify(ls[x],ll,rr,cc);
  if rr>mid then modify(rs[x],ll,rr,cc);
  relax(ls[x]); relax(rs[x]);
  if c[ls[x]]=c[rs[x]] then c[x]:=c[ls[x]]
  else c[x]:=-1;
end;


procedure find(x,ll,rr:longint);
var
  mid:longint;
begin
  relax(x);
  if (ll<=l[x])and(r[x]<=rr) then
  begin
    if c[x]>=0 then b[c[x]]:=true
    else begin
      find(ls[x],ll,rr); find(rs[x],ll,rr);
    end;
    exit;
  end;
  mid:=(l[x]+r[x])div 2;
  if ll<=mid then find(ls[x],ll,rr);
  if rr>mid then find(rs[x],ll,rr);
end;


Begin
  assign(input,'poj.in'); reset(input);
  assign(output,'poj.out');rewrite(output);
  readln(len,t,o);
  t:=1;
  build(1,1,len);
  for i:=1 to o do
  begin
    read(ch);
    if ch='C' then
    begin
      readln(ll,rr,cc);
      modify(1,ll,rr,cc);
    end
    else begin
      readln(ll,rr);
      fillchar(b,sizeof(b),0);
      find(1,ll,rr);
      ans:=0;
      for j:=1 to t do if b[j] then inc(ans);
      writeln(ans);
    end;
  end;
  close(input);close(output);
End.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FarmerJohn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值