HDU 1754 线段树

要求:学生ID编号分别从1编到N。
第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩。
接下来有M行。每一行有一个字符 C (只取'Q'或'U') ,和两个正整数A,B。
当C为'Q'的时候,表示这是一条询问操作,它询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少。
当C为'U'的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。

方法:线段树。

1.update用while写不用递归。

2.query用递归求解。

3.重点是把树补成满二叉树。

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#define inf -1
using namespace std;
int k,n,m,qr,ql,a[1000005],b[1000005],maxv[1000005];
int query(int o,int L,int R)
{
	int i,j,k;
	int M=L+(R-L)/2,ans=inf;
	if(ql<=L&&R<=qr)
	  return maxv[o];
	if(ql<=M) ans=max(ans,query(o*2,L,M));
	if(M<qr)  ans=max(ans,query(o*2+1,M+1,R));
	return ans;
}
void update(int o)
{
	int i,j,k;
	while(o>=1)
	{
	 o/=2;
	 maxv[o]=max(maxv[o*2],maxv[o*2+1]);
	}
}
int main()
{
   int i,j,ans; 
   char c;
   while(scanf("%d%d",&n,&m)!=EOF)
   {
   	 memset(a,0,sizeof(a));
   	 memset(b,0,sizeof(b));
   	 memset(maxv,inf,sizeof(maxv));
   	 k=ceil(log(n)/log(2));
   	 ans=1;
	 for(i=0;i<k;i++)
	  ans*=2;
	 for(i=1;i<=n;i++)
   	 {
   	   scanf("%d",&a[i]);	
   	   maxv[i+ans-1]=a[i];
   	   update(i+ans-1);
	 }
	 /*for(i=1;i<=ans2*2-1;i++)
	   printf("a%d=%d\n",i,maxv[i]);*/
	 /*for(i=1;i<=ans*2-1;i++)
	   printf("a%d=%d\n",i,maxv[i]);*/
	 for(i=0;i<m;i++)
	 {
	 	getchar();
	 	scanf("%c%d%d",&c,&ql,&qr);
	 	if(c=='Q')
	 	 printf("%d\n",query(1,1,ans));	
		else
		{
		  maxv[ql+ans-1]=qr;	
		  update(ql+ans-1);
		  /*for(j=1;j<=ans*2-1;j++)
	       printf("a%d=%d\n",j,maxv[j]);*/	
		}
	 }
   }
}

猜你喜欢

转载自blog.csdn.net/Irving0323/article/details/83099422