原题连接:http://acm.hdu.edu.cn/showproblem.php?pid=1754
题意:说的很清楚,不必过多的解释了……
思路:线段树的求区间最值……解释在代码里
AC代码:
/* 线段树 -求区间最值之改点 1:线段树中存的是 区间的最值 2:建线段树时 到单点时回溯回去,更新出该点父节点(一直向上到根节点)的最值 3:改变某一点值时,找到该点所在区间节点,回溯回去,更新父节点的最值 4:查询区间最值时,找到对应的的所有小区间,求出最值即可。 */ #include<stdio.h> #include<string.h> #define Max 4*1000000 #define LL(a) a<<1; //2*A #define RR(a) a>>1|1; //2*a+1 #define Mid(x,y) (x+y)>>1 //(x+y)/2 int A[Max],ans,cnt; struct hello { int l; int r; int max; //存的是该区间的最值 }tree[Max]; void Build_tree(int l,int r,int t) // l,r 表示区间,t表示 区间节点 { int x; tree[t].l=l; tree[t].r=r; tree[t].max=0; if(l==r) { while(t) { if(tree[t].max<A[l]) tree[t].max=A[l]; t/=2; } return ; } x=Mid(l,r); Build_tree(l,x,2*t); Build_tree(x+1,r,2*t+1); } void Updata_tree(int l,int r,int t) { if(tree[t].l==l&&tree[t].r==r) { tree[t].max=cnt; while(t) { t/=2; tree[t].max= tree[2*t].max>tree[2*t+1].max?tree[2*t].max:tree[2*t+1].max; } return ; } int x=Mid(tree[t].l,tree[t].r); if(x>=r) Updata_tree(l,r,2*t); else if(x+1<=l) Updata_tree(l,r,2*t+1); else { Updata_tree(l,x,2*t); Updata_tree(x+1,r,2*t+1); } } void Query_tree(int l,int r,int t) { if(tree[t].l==l&&tree[t].r==r) { if(ans<tree[t].max) ans=tree[t].max; return ; } int x=Mid(tree[t].l,tree[t].r); if(x>=r) Query_tree(l,r,2*t); else if(x+1<=l) Query_tree(l,r,2*t+1); else { Query_tree(l,x,2*t); Query_tree(x+1,r,2*t+1); } } int main() { int i,j,n,m,ncase; while(~scanf("%d%d",&n,&m)) { for(i=1;i<=n;i++) scanf("%d",&A[i]); Build_tree(1,n,1); while(m--) { char str[10]; int x,y; scanf("%s%d%d",str,&x,&y); if(str[0]=='Q') { ans=0; Query_tree(x,y,1); printf("%d\n",ans); } else { cnt=y; Updata_tree(x,x,1); } } } }