刚刚接触到线段树 , 所谓线段树,就是每个节点存储着数组中某一段的信息(最值或者其他),而叶子节点段长是1,就是数组中的某一个数。
主要操作是建树 , 查询,更新等。
下面是代码,题目参考 HDU 1754 I hate it
注释很详细,可以仔细看,逻辑并不是很复杂、
#include <cstdio>
#include <algorithm>
using namespace std;
//线段树 数组实现
#define MAX_NODE 200001
int in[MAX_NODE];
int segtree[4*MAX_NODE+10];
int build_tree(int root , int left , int right){
if (left == right){
segtree[root] = in[left];
// printf("node = %d value = %d\n" ,root, in[left]);
return -1;
}
if (right<left)
return -1;
int mid = (left+right)/2;
build_tree(root*2 , left , mid);
build_tree(root*2+1 , mid+1 , right);
segtree[root] = max(segtree[root*2] , segtree[root*2+1]);
}
int query_tree(int root , int left , int right , int start ,int end){//找出start 到 end 区间的最值
if(start>right || end<left)//如果该节点记录的区间与查询的区间没有交集
return -1;
if (left>=start && right<=end)//如果该节点记录的区间是查询区间的子集
return segtree[root];
//剩余情况就是 该节点记录的区间大于待查询的区间 或者 该节点记录的区间与待查询区间有交集
// 节点记录区间大于待查询区间时,继续递归查询左右子树
//节点记录的区间与待查询区间有交集 , 左右子树总有一个是记录待查询区间的子集
int mid = (left+right)>>1;
int part1 = query_tree(root*2 , left ,mid,start,end);//查询左子树
int part2 = query_tree(root*2+1 , mid+1 , right ,start , end);//查询右子树
//下面两个判断是针对节点记录的区间与待查询区间有交集但不是待查询区间的子集。这样肯定左右子树中有一个包含了待查询区间的子集
if (part1 == -1)//如果左子树不包含待查询区间
return part2;
if (part2 == -1)//如果右子树不包含待查询区间
return part1 ;
//节点记录区间大于待查询区间时,此时左右子树都包含了待查询区间,所以取左右子树返回的一个最大值最为待求区间的最大值
return max(part1,part2);//
}
int update_tree(int root , int left , int right , int updatenode , int value){//updatenode是待更新的节点的区间值,value是该节点的值
if (left == right){
segtree[root] = value;
return -1;
}
int mid = (left+right)>>1;
if (mid<updatenode){
update_tree(root*2+1,mid+1,right,updatenode, value);
}else{
update_tree(root*2,left,mid,updatenode,value);
}
//回溯更新父节点
segtree[root] = max(segtree[root*2],segtree[root*2+1]);
}
int main (){
int m,n;
while (~scanf("%d%d",&n,&m)){
for (int i = 0 ; i < n ; i ++)
scanf("%d",&in[i]);
build_tree(1,0,n-1);//root 根节点号码必须从大于0的数开始
char c;
int a,b;
for (int i= 0 ; i < m ; i ++){
scanf("\n%c%d%d",&c,&a,&b);
if (c=='Q')
printf("%d\n",query_tree(0,0,n-1,a,b));
else
update_tree(0,0,n-1,a-1,b);
}
}
}