这个题目是比较简单的线段树,不过还是想说几句。这个线段树涉及到的操作有建树(这不是废话吗,线段树怎么能不建树呢!),还有就是更新和询问操作。为了节省时间,我们可以把非叶子节点可以用来记录这个区间的最大分数,如果访问到这个区间,直接输出最大分数值就可以了,不必要每次都询问到叶子节点。更新就得说一下了。我写成这样root==id程序就不能运行,但是写成tree[root].l==id&&tree[root].r==id就可以得出结果了,还有就是,你要更新叶子节点的值,还需要执行的一个操作就是从下往上也要更新非叶子节点的值,保持线段树的非叶子节点记录的是区间上的最大值。回溯理解了,那么从下往上的更新也就不难理解。
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 200003
struct SegTree
{
int l,r,mid;
int score;
}tree[N*3];
int s[N];
int max(int a,int b)
{
return a>b?a:b;
}
void BuildTree(int root,int l,int r)
{
tree[root].l=l;
tree[root].r=r;
tree[root].mid=(l+r)/2;
if(l==r)
{
tree[root].score=s[l];
return ;
}
BuildTree(2*root,l,tree[root].mid);
BuildTree(2*root+1,tree[root].mid+1,r);
tree[root].score=max(tree[2*root].score,tree[2*root+1].score);
}
int Query(int root,int l,int r)
{
if(l<=tree[root].l&&tree[root].r<=r)
{
return tree[root].score;
}
if(tree[root].mid<l)
{
return Query(2*root+1,l,r);
}
else if(tree[root].mid>=r)
{
return Query(2*root,l,r);
}
else
{
return max(Query(2*root,l,tree[root].mid),Query(2*root+1,tree[root].mid+1,r));
}
}
void Updata(int root,int id,int key)
{
if(tree[root].l==id&&tree[root].r==id)
{
tree[root].score=key;
return;
}
if(id<=tree[root].mid)
{
Updata(2*root,id,key);
}
else
{
Updata(2*root+1,id,key);
}
tree[root].score=max(tree[2*root].score,tree[2*root+1].score);
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&s[i]);
}
BuildTree(1,1,n);
while(m--)
{
char ch[3];
scanf("%s",ch);
if(ch[0]=='Q')
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",Query(1,a,b));
}
else if(ch[0]=='U')
{
int a,b;
scanf("%d%d",&a,&b);
Updata(1,a,b);
}
}
}
return 0;
}