1099: 线段树(元问题)线性结构求极值和修改

1099: 线段树(元问题)线性结构求极值和修改

20171109更新详解

时间限制: 1 Sec 内存限制: 128 MB
【题意】
给出N个数,两种操作:
1、C x y:修改第x个数的值为y;
2、P x y:求第x到第y个的最大值,注:x未必比y小
【输入格式】
第一行输入N和M(0<N<=200000,0<M<5000),N表示有N个数,M表示有M个操作
下来N个数
然后是M个操作。
【输出格式】
遇到P操作的时候,输出结果。
【样例输入】
5 6
1 2 3 4 5
P 1 5
C 3 6
P 3 4
P 4 5
C 2 9
P 1 5
【样例输出】
5
6
5
9

Solution

如果纯模拟,时间肯定会超
线段树的元问题
c++翻译一下pascal的线段树模板,我来做一个pascal版本的线段树模板吧。
话说noip还是报了pascal,c++和pascal的翻译水平越来越熟练了~~
话说读入问题昨天找了许长时间都找不出来错误,,,,害死人
(c++我直接在caioj复制过来了,应该不侵权吧…)

Code

type
  node=record
    l,r,lc,rc,c:longint;//l,r为范围,lc,rc为左孩子与右孩子,c为特征值
  end;
var tr:array[0..410000]of node;
    a:array[0..210000]of longint;
    len,i,j,n,m,x,y:longint;
    ss:char;
function mymax(p,q:longint):longint;
begin
  if p>q then exit(p)
  else exit(q);
end;

procedure buildtree(l,r:longint);
var now,mid:longint;
begin
  inc(len); //申请管理者
  now:=len; //记录当前编号
  tr[now].l:=l; tr[now].r:=r; tr[now].lc:=-1; tr[now].rc:=-1;//初始
  if l=r then tr[now].c:=a[l]  //只管一个人,则对应c
  else
  begin              //若管理人数大于等于2
    mid:=(l+r)div 2;
    tr[now].lc:=len+1;buildtree(l,mid);//编号,l,mid给左孩子
    tr[now].rc:=len+1;buildtree(mid+1,r);//同上
    tr[now].c:=mymax(tr[tr[now].lc].c,tr[tr[now].rc].c);//上述就位后询问最大值为多少并记录
  end;
end;

procedure change(now,x,k:longint);  //告诉头领(now),x的位置改成k
//修改的是管理者不是员工的值
var mid,lc,rc:longint;
begin
  if tr[now].l=tr[now].r then begin tr[now].c:=k; exit; end; //找到最基层
  lc:=tr[now].lc;   rc:=tr[now].rc;
  mid:=(tr[now].l+tr[now].r)div 2;
  if x<=mid then change(lc,x,k)
  else  if mid+1<=x then change(rc,x,k);

  tr[now].c:=mymax(tr[lc].c,tr[rc].c);//改完后询问维护最大值
end;

function findmax(now,l,r:longint):longint;//
var lc,rc,mid:longint;
begin
  if (l=tr[now].l)and(tr[now].r=r) then exit(tr[now].c);//找到就输出

  lc:=tr[now].lc;   rc:=tr[now].rc;
  mid:=(tr[now].l+tr[now].r)div 2;
  if r<=mid then exit(findmax(lc,l,r))
  else if mid+1<=l then exit(findmax(rc,l,r))
  //下方为一部分在左child与右child里
  else exit(mymax(findmax(lc,l,mid),findmax(rc,mid+1,r)));
end;

begin

  readln(n,m);
  for i:=1 to n do
  begin
    if i<>n then
    read(a[i])
    else readln(a[i]); //注意读入,害死人qwq
  end;
  //读入数据
  len:=0; buildtree(1,n);
  //初始管理员为0,在1,n范围建树

  for i:=1 to m do
  begin
    read(ss);
    readln(x,y);//注意读入!!!
    if ss='C' then change(1,x,y)
    else
    begin
      if (x>y) then writeln(findmax(1,y,x))
      else writeln(findmax(1,x,y));
    end;
  end;
end.

c++版本放下面

上面的图片来自caioj,pascal版本为翻译

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值