hdu1754


I Hate It

给定一个 数组,当输入Q A B 的时候是查询从A-B的区间的最大值,当输入为U A B 的时候,就是把第A个数换成B,然后更新数组


5 6
1 2 3 4 5
Q 1 5
U 3 6
Q 3 4
Q 4 5
U 2 9
Q 1 5


5
6
5

#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,不然就会出错。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值