本题涉及线段树的区间查询最大值与单点更新,属于一道模板题。
代码如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=2e5+5;
struct Node
{
int l,r;
int ma;
}tr[maxn<<2];
int a[maxn];
void Push_Up(int rt)
{
tr[rt].ma=max(tr[rt<<1].ma,tr[rt<<1|1].ma);
}
void Build(int rt,int l,int r)
{
tr[rt].l=l; tr[rt].r=r;
if(l==r)
{
tr[rt].ma=a[l];
return;
}
int mid=(l+r)>>1;
Build(rt<<1,l,mid);
Build(rt<<1|1,mid+1,r);
Push_Up(rt);
}
void Update(int rt,int ql,int qr,int val)
{
if(ql==tr[rt].l&&tr[rt].r==qr)
{
tr[rt].ma=val; //单点修改
return;
}
int mid=(tr[rt].l+tr[rt].r)>>1;
if(mid<ql) Update(rt<<1|1,ql,qr,val);
else if(mid>=qr) Update(rt<<1,ql,qr,val);
else
{
Update(rt<<1,ql,mid,val);
Update(rt<<1|1,mid+1,qr,val);
}
Push_Up(rt); //Update结尾记得Push_Up,经常要忘了这一步
}
void Query(int rt,int ql,int qr,int &ma)
{
if(ql<=tr[rt].l&&tr[rt].r<=qr)
{
ma=max(tr[rt].ma,ma);
return;
}
if(tr[rt].l==tr[rt].r) return; //到了叶子节点就可以返回了
int mid=(tr[rt].l+tr[rt].r)>>1;
if(mid<ql) Query(rt<<1|1,ql,qr,ma);
else if(mid>=qr) Query(rt<<1,ql,qr,ma);
else
{
Query(rt<<1,ql,mid,ma);
Query(rt<<1|1,mid+1,qr,ma);
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
Build(1,1,n);
while(m--)
{
char s[2];
int a,b;
scanf("%s%d%d",s,&a,&b);
if(s[0]=='Q')
{
int ma=0;
Query(1,a,b,ma);
printf("%d\n",ma);
}
else Update(1,a,a,b);
}
}
return 0;
}