hdu1754 树状数组
单点更新,区间求最值(也可以用线段树)
#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);
}
}
}
}

浙公网安备 33010602011771号