您的位置:首页 > 其它

hdu 1754 线段树

2012-06-22 19:16 169 查看
//这次换了种写法写线段树,加深了自己的理解
//6091831	2012-06-22 19:09:25	Accepted	1754	1234MS	8180K	1358 B	C++	chen
#include<iostream>
using namespace std;

int n;
//表示某个节点的左右
int lef[200000*4];
int righ[200000*4];
//表示左儿子和右儿子的编号
int lson[200000*4];
int rson[200000*4];
int sum[200000*4];
char ch;

int Max(int a,int b){
	return a>b?a:b;
}
//刚开始的写法是先定义全局变量p,q
//else if(b-a>0){
//	p=n+1;
//	lson[v]=p
//	build(a,(a+b)/2);
//	q=n+1;
//	rson[v]=q;
//	build((a+b)/2+1,b);
//	sum[v]=Max(sum[p],sum[q]);
//}
//这样写的话会出错,我现在还想不明白什么原因
//创建线段树
void build(int a,int b){
	n++;
	int v=n;
	lef[v]=a;
	righ[v]=b;
	if(a==b){
		scanf("%d",&sum[v]);
		return;
	}
	else if(b-a>0){
		lson[v]=n+1;
		build(a,(a+b)/2);
		rson[v]=n+1;
		build((a+b)/2+1,b);
		sum[v]=Max(sum[lson[v]],sum[rson[v]]);
	}
}
//询问【a,b】中【c,d】的最大值
int query(int a,int b,int root){
	if(a<=lef[root]&&b>=righ[root]){
		return sum[root];
	}
	int res=0;
	int mid=(lef[root]+righ[root])/2;
	//这儿一定要加上等号,因为这儿的划分是【1,2】划分为【1,1】和【2,2】
	//比如说要寻找1,此时mid=1,如果不加上等号的话,则会在rson中寻找也就是【2,2】中寻找,这是找不到的
	if(a<=mid)
		res=Max(res,query(a,b,lson[root]));
	if(b>mid)
		res=Max(res,query(a,b,rson[root]));
	return res;
}

//更新,不过这只是单点更新
void update(int a,int add,int root){
	if(lef[root]==righ[root]){
		sum[root]=add;
		return;
	}
	int mid=(lef[root]+righ[root])/2;
	if(a<=mid)
		update(a,add,lson[root]);
	else
		update(a,add,rson[root]);
	sum[root]=Max(sum[lson[root]],sum[rson[root]]);
}

int N,M,c,d;

int main(){
	while(scanf("%d%d",&N,&M)!=EOF){
		n=0;
		build(1,N);
		while(M--){
			cin>>ch>>c>>d;
			if(ch=='Q')
				cout<<query(c,d,1)<<endl;
			if(ch=='U')
				update(c,d,1);
		}
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: