【解题报告】 HDU 1754 I Hate It 线段树 单点更新

题目连接: HDU 1754
这个是线段树的基本操作----更新和查询,属于基础水题,我就不说什么了。
如果不知道线段树的基本操作,请移步 线段树的基本操作
// HDU 1754  I Hate It  线段树 -- 单点更新
// 有效结点: 20w
// 深度达到:(lg20w)/(lg2) +1 .= 18.61 .= 19
// 其完全二叉树 总结点 个数为: (1<<19) - 1 个
// 区间最大值问题
//
/*test data
5 6
1 2 3 4 5
Q 1 5
U 3 6
Q 3 4
Q 4 5
U 2 9
Q 1 5

*/
#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;

const int MAXNODE = 524288; // 1<<19
const int MAXST = 200001;
struct STU{
	int grade;
	int left,right;
}st[MAXNODE];

int father[MAXST];

void BuildTree(int i,int left,int right){ // i是结点的序号 对应了数组下标
	st[i].left = left;
	st[i].right = right;
	st[i].grade = 0; // 初始化为0
	if (left == right){
		father[left] = i; // 为了更新的时候从下往上 一直到顶
		return;
	}
	BuildTree(i<<1, left, (int)floor( (right+left) / 2.0));
	BuildTree((i<<1) + 1, (int)floor( (right+left) / 2.0) + 1, right);
}

void UpdataTree(int ri){ // 从下往上更新

	if (ri == 1){return;}
	int fi = ri / 2; // 父结点
	int a = st[fi<<1].grade; // 该父结点的两个子结点
	int b = st[(fi<<1)+1].grade;
	st[fi].grade = (a > b)?(a):(b);
	UpdataTree(ri/2);

}

int Max;
void Query(int i,int l,int r){ // i为区间的序号,四段查询 即四种情况

	if (st[i].left == l && st[i].right == r){ // 找到了一个完全重合的区间
		Max = (Max < st[i].grade)?st[i].grade:(Max);
		return ;
	}
	i = i << 1; // left child of the tree
	if (l <= st[i].right){ // 左区间有覆盖
		if (r <= st[i].right) // 全包含于左区间
			Query(i, l, r);
		else // 半包含于左区间
			Query(i, l, st[i].right);
	}
	i += 1; // right child of the tree
	if (r >= st[i].left){ // 右区间有覆盖
		if (l >= st[i].left) // 全包含于右区间
			Query(i, l, r);
		else // 半包含于左区间
			Query(i, st[i].left, r);
	}
}

int main()
{
//	freopen("in.txt","r",stdin);
	int n_s,n_q,igrade; 
	while(scanf("%d %d",&n_s,&n_q) != EOF){
		BuildTree(1, 1, n_s); 
		for (int i= 1 ; i <= n_s; i++){
			scanf("%d",&igrade);
			st[father[i]].grade = igrade; // 底层的无条件更新成绩
			UpdataTree(father[i]);
		}
		while(n_q--){
			char o[3];int a,b;
			scanf("%s %d %d",o,&a,&b);
			if ( o[0] == 'Q'){
				Max = 0;
				Query(1, a, b);
				printf("%d\n",Max);
			}else{
				st[father[a]].grade = b; // 底层的无条件更新成绩
				UpdataTree(father[a]);
			}
		}
	}
	return 0;
}

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值