1. 程式人生 > >HDU 1754 線段樹

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]);*/	
		}
	 }
   }
}