HDU 1754 線段樹
阿新 • • 發佈:2018-12-04
要求:學生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]);*/ } } } }