hdu1754 树状数组

单点更新,区间求最值(也可以用线段树)

图: http://baike.baidu.com/picview/1420784/1420784/0/55a628d10b98f02b9a50276e.html#albumindex=0&picindex=0

#include<stdio.h>
#include<string.h>
int n,num[200009],p[200009];
int max(int a,int b)
{
	return a>b?a:b;
}
int lowbit(int t)
{
	return t&(-t);
}
void change()//找最大值的初始化 
{   int i,j;
	for(i=1;i<=n;i++)//用p[i]记录i所管辖的范围内的最大值 
	{  
	    p[i]=num[i];
		//先将第i个值记为最大值,再与i所管辖的点的p[]值比较,(根据树状数组的图来理解)
		//p[]已经是 它所管辖点的最大值 ,这样就可以实现用p[i]记录i所管辖的范围内的最大值 
		for(j=1;j<lowbit(i);j=j*2)
		{
			p[i]=max(p[i],p[i-j]);//j以2的倍数增长 
		}
	}
}
int getmax(int l,int r)//找l到r之间的最大值 
{   
	int ans=num[r];
	for(;;)
	{
		if(ans<num[r]) ans=num[r];
	  //跟r位置上的数字比较 ,一定要有这个,例如求4到5的最大值,没有这个会漏比较4; 
		if(l==r) break;
		for(r=r-1;r-lowbit(r)>=l;r=r-lowbit(r))
		{   
		//r自减1,判断r-lowbit(r)和l之间的关系如果l在区间内就不能减了而是继续循环 
			if(p[r]>ans) ans=p[r];
		}
		//这里即使没有进入循环体内,r也已经自减了1 
	}
	return ans;
}
void insert(int t,int score)//更新,改变num[t]的值,则它的父节点的p[]也要更新 
{
	num[t]=score;
	while(t<=n)
	{
		if(score>p[t])
		p[t]=score;
		else break;//这里还不是很明白,如果是1 2 3 4 5 ,改成1 2 3 4 4,那不是
		           //p[5]还是5 
		t=t+lowbit(t);//求t的父节点 
	}
}
int main()
{   int m,i,a,b,Max;
    char str[9];
	while(scanf("%d%d",&n,&m)!=EOF)
	{   
		for(i=1;i<=n;i++)
		scanf("%d",&num[i]);
		memset(p,0,sizeof(p));//要记得初始化 
		change();
		for(i=1;i<=m;i++)
		{
			scanf("%s%d%d%*c",&str,&a,&b);
			if(str[0]=='Q')
			{
				Max=getmax(a,b);
				printf("%d\n",Max);
			}
			else if(str[0]=='U')
			{
				insert(a,b);
			}
		} 
	}
}

 

http://baike.baidu.com/picview/1420784/1420784/0/55a628d10b98f02b9a50276e.html#albumindex=0&picindex=0

posted @ 2013-04-15 13:02  宛如  阅读(194)  评论(0编辑  收藏  举报