HDU

  这个也是线段树的经验问题,待修改的,动态询问区间的最大值,只需要每次更新的时候,去把利用子节点的信息进行修改即可以。

  注意更新的时候区间的选择,需要对区间进行二分。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxx = 200003;
int b[maxx];
struct node{
  int l;
  int r;
  int mid;
  int high;
}a[maxx*4];
void pushup(int root){
   a[root].high=max(a[root*2].high,a[root*2+1].high);//把修改往上传递
}
void buildtree(int root,int l,int r){
    a[root].l=l;
    a[root].r=r;
    if(l==r){//到叶子节点
        a[root].high=b[l];
        return;
    };
    int mid=(l+r)/2;
    buildtree(root*2,l,mid);//注意不要写错
    buildtree(root*2+1,mid+1,r);
    pushup(root);//把叶子节点的信息给传递上去
}
void update(int root,int pos,int c){//单点修改
    int l=a[root].l;
    int r=a[root].r;
    if(l==r){
        a[root].high=c;//修改
        return;
    };
    int mid=(l+r)/2;
    if(pos<=mid){
        update(root*2,pos,c);
    }else {
        update(root*2+1,pos,c);
    }
    pushup(root);
}
int query(int root,int ql,int qr){//询问的区间是不变的,因为每次要判断
   int l=a[root].l;
   int r=a[root].r;
   int mid=(l+r)/2;
   int high=0;
   if(ql<=l && r<=qr){//如果询问区间是完全大于当前节点表示的区间直接返回当前节点的信息
    return a[root].high;
   }
   //那么代表询问区间和当前节点表示的区间有交集,当前节点的区间信息中只有一部分是我们想到得到的
   if(ql<=mid){//因此我们需要对区间节点二分毕竟建树就是这么建立的
    high=query(root*2,ql,qr);//如果这个询问左边界范围是在中间节点的左边,我们需要询问进一步询问左儿子节点
   };
   if (qr>mid){//如果这个询问的右边界是在中间节点的右边,我们需要进一步询问右儿子节点
    high=max(high,query(root*2+1,ql,qr));
   }
   return high;
}
int main(){
  int n,m;
  while(~scanf("%d%d",&n,&m)){
    for (int i=1;i<=n;i++){
        scanf("%d",&b[i]);
    }
    buildtree(1,1,n);
    int tmp1,tmp2;
    char op;
    for (int i=1;i<=m;i++){
        scanf(" %c%d%d",&op,&tmp1,&tmp2);
        if (op=='Q'){
           int ans=query(1,tmp1,tmp2);
           printf("%d
",ans);
        }else {
           update(1,tmp1,tmp2);
        }
    }
  }
  return 0;
}
有不懂欢迎咨询 QQ:1326487164(添加时记得备注)
原文地址:https://www.cnblogs.com/bluefly-hrbust/p/10326743.html