題目:
很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。
這讓很多學生很反感。
不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程序,模擬老師的詢問。當然,老師有時候需要更新某位同學的成績。
Input
本題目包含多組測試,請處理到文件結束。
在每個測試的第一行,有兩個正整數 N 和 M ( 0<N<=200000,0<M<5000 )
,分別代表學生的數目和操作的數目。
學生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。
Output
對於每一次詢問操作,在一行裏面輸出最高成績。
Sample Input
5 6
1 2 3 4 5
Q 1 5
U 3 6
Q 3 4
Q 4 5
U 2 9
Q 1 5
Sample Output
5
6
5
9
Hint
Huge input,the C function scanf() will work better than cin
思路:
線段樹模板題。優化解題速度的方法用位運算,用while語句。先用遞歸的思路建立線段樹,再同樣用遞歸的思路維護線段樹。
附上代碼:
#include <iostream>
#include<cstdio>
using namespace std;
#define MAXN 200005
int num[MAXN];
int tree[MAXN*4];
void build_tree(int p,int l,int r)
{
if(l==r){tree[p]=num[l];return;}
int mid=(l+r)>>1;
build_tree(p<<1,l,mid);
build_tree(p<<1|1,mid+1,r);
tree[p]=max(tree[p<<1],tree[p<<1|1]);
}
//遞歸建樹
void change(int p,int l,int r,int x,int num)
{
if(l==r){tree[p]=num;return;}
int mid=(l+r)>>1;
if(x<=mid)change(p<<1,l,mid,x,num);
else change(p<<1|1,mid+1,r,x,num);
tree[p]=max(tree[p<<1],tree[p<<1|1]);
//根節點的更新
}//修改樹
int Find(int p,int l,int r,int x,int y)
{
if(x<=l&&y>=r){return tree[p];}
int mid=(l+r)>>1;
if(y<=mid)return Find(p<<1,l,mid,x,y);
if(x>mid)return Find(p<<1|1,mid+1,r,x,y);
return (max(Find(p<<1,l,mid,x,mid),Find(p<<1|1,mid+1,r,mid+1,y)));
}//查找區間信息的和
int main()
{
int N,M;
int i;
char s[2];//輸入字符
int x,y;
while(scanf("%d%d",&N,&M)!=EOF)//當輸出不再輸出時
{
for(i=1;i<=N;i++)
{
scanf("%d",&num[i]);
}
build_tree(1,1,N);//建樹
while(M--)
{
scanf("%s%d%d",s,&x,&y);
if(s[0]=='Q'){
printf("%d\n",Find(1,1,N,x,y));
}
else{
change(1,1,N,x,y);
}
}
}
return 0;
}