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); } } } }