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++版本放下面