#include<iostream>
#include<algorithm>
using namespace std;
int arry[200001];//初始数值
const int MaxNum=200010;
struct Tree //线段树的区间结点
{
int L,R; //某结点的区间范围
int Max; //区间最值
}tree[4*MaxNum];
void BuildTree(int curr,int l,int r)//建立线段树
{
tree[curr].L=l;
tree[curr].R=r;
if(l==r) //到达根节点,即为单点的值
{
tree[curr].Max=arry[r];//单点最值是本身
return;
}
int mid=(l+r)/2;
BuildTree(curr*2,l,mid);//建左区间线段
BuildTree(curr*2+1,mid+1,r);//建右线段
tree[curr].Max=max(tree[curr*2].Max , tree[curr*2+1].Max);//回溯更新父结点的最值
}
int Query(int curr, int l, int r)//区间查询l到r,curr为当前讨论线段
{
if(tree[curr].L==l && tree[curr].R==r)//区间匹配,返回最值
return tree[curr].Max;
int mid =(tree[curr].L+tree[curr].R)/2;
if(r <=mid)
return Query(curr*2, l,r);//要找的区间在当前curr线段的左子树
else if(l >mid)
return Query(curr*2+1, l,r);//在右子树
else
return max( Query(curr*2, l,mid), Query(curr*2+1, mid+1, r) );//要找区间跨在当前线段左右子树
}
void Update(int curr, int pos, int value)//单点更新,pos表示需更新的结点
{
if(tree[curr].L== pos && pos == tree[curr].R)//到达叶子结点,更新
{
tree[curr].Max=value;
return;
}
int mid=(tree[curr].L+tree[curr].R)/2;
if(pos <=mid) //需更新结点在当前线段的左子树
Update(curr*2, pos,value);
else
Update(curr*2+1,pos,value);//在右子树
tree[curr].Max=max( tree[curr*2].Max, tree[curr*2+1].Max );//修改完后回溯时更新最值
}
int main()
{
int n,m;
int i,a,b;
char c;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%d",&arry[i]);
BuildTree(1,1,n); //建区间大小为1到n的线段树
for(i = 1 ; i <= m ; i ++)
{
cin>>c>>a>>b;
if(c=='Q')
{
cout<<Query(1, a, b)<<endl;//查询a到b的最大值
}
else
Update(1, a, b);//修改a的值为b
}
}
return 0;
}
HDU1754
最新推荐文章于 2019-10-25 00:39:07 发布