#include<stdio.h>
#include<string.h>
const int n=131072*2+1;
int rmax[n<<2];
int a[n];
int max(int a,int b){
return a>=b?a:b;
}
void build(int root,int l,int r){
if(r==l){
rmax[root]=a[l];
return;
}
int mid=(l+r)>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
rmax[root]=max(rmax[root<<1],rmax[root<<1|1]);
}
int querymax(int root,int L,int R,int l,int r){
if(l<=L&&r>=R){
return rmax[root];
}
int mid=(L+R)>>1;
int ma=0;
if(mid>=l)
ma=max(ma,querymax(root<<1,L,mid,l,r));
if(mid<r)
ma=max(ma,querymax(root<<1|1,mid+1,R,l,r));
return ma;
}
void update(int root,int l,int r,int p,int v){
int mid=(l+r)>>1;
if(l==r){
rmax[root]=v;
return;
}
else
{
if(p<=mid)
update(root<<1,l,mid,p,v);
else
update(root<<1|1,mid+1,r,p,v);
rmax[root]=max(rmax[root<<1],rmax[root<<1|1]);
}
}
int main(){
int x,m;
while(scanf("%d%d",&x,&m)!=EOF)
{
memset(rmax,0,sizeof(rmax));
for(int i=1;i<=x;i++)
scanf("%d",&a[i]);
char k;
int l,r;
build(1,1,x);
while(m--){
getchar();
scanf("%c%d%d",&k,&l,&r);
if(k=='Q')
printf("%d\n",querymax(1,1,x,l,r));
if(k=='U')
update(1,1,x,l,r);
}
}
return 0;
}
这道题目和之前POJ上做的那道题目差不多,唯一的区别就是这个题目多了一个节点的更新
不过大体思想差不多
刚开始建树的时候用一个数组去保存每个子树的最大值,然后查询的时候用一个max不断去比较子树根节点所存的值,遇到比max大的值就更新,最后得到这个区间的最大值
改变的节点的值得时候,先判断一下这个节点在
线段树的哪棵子树上,不断调用update这个函数,动态更新每个节点上的最大值,当更新到
叶子节点的时候就直接赋值。
不过自己在提交代码的时候犯了一个很笨的错误,在写querymax这个函数的时候,最后忘记写返回值了,导致一直WA,这个主意一下
还有就是在建树的时候,更新叶子节点的时候,必须写return,不然就会出错。