刚刚开始学线段树,看见中文题就很开心~
线段树是一种二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。
这题的查询要求是得到区间内成绩最好的那个。查区间,故用线段树。
首先,要建立一颗线段树,每个根结点的值是两个子结点里更大的那个。
然后,开始查,就是对比区间,有三种情况,老师给出的区间不在区间里,给出的区间完全被包含在区间里,给出的区间部分包含在区间里
第一种可以直接返回了,第二种直接输出该区间的最大值,第三种还得两边继续往下查
这是查找
还有更新,知道是哪个点,一直更~
//线段树的建立,维护最大值和单点更新
#include<stdio.h>
#define maxn 200010
#define maxm 5010
struct node{
int left,right,max;
}tree[maxn<<2];
int grade[maxn];
int build(int root,int left,int right)
{
int mid;
tree[root].left=left;
tree[root].right=right;
//已经是最下面了
if(left==right)
{
return tree[root].max=grade[left];
}
mid=(left+right)/2;
int x,y;
x=build(2*root,left,mid);//左子树
y=build(2*root+1,mid+1,right);//右子树
return tree[root].max=x>y?x:y;
}
int query(int root,int left,int right)
{
//不在区间
if(tree[root].left>right||tree[root].right<left)
return 0;
//包含区间那可以结束了
if(tree[root].left>=left&&tree[root].right<=right)
return tree[root].max;
int x,y;
x=query(root*2,left,right);
y=query(root*2+1,left,right);
return x>y?x:y;
}
int update(int root,int num,int value)
{
//不在区间
if(tree[root].left>num||tree[root].right<num)
return 0;
//找到那个节点
if(tree[root].left==num&&tree[root].right==num)
return tree[root].max=value;
int x,y;
x=update(root*2,num,value);
y=update(root*2+1,num,value);
return tree[root].max=x>y?x:y;
}
int main()
{
int n,m,a,b;
char op;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&grade[i]);
}
build(1,1,n);
for(int i=1;i<=m;i++)
{
getchar();
scanf("%c%d%d",&op,&a,&b);
if(op=='Q')
{
printf("%d\n",query(1,a,b));
}
else
{
grade[a]=b;
update(1,a,b);
}
}
}
return 0;
}
本文介绍了一种数据结构——线段树,并通过一个具体题目详细解释了如何利用线段树来高效解决区间查询问题,包括线段树的构建、查询及更新操作。
1万+

被折叠的 条评论
为什么被折叠?



