这道题比较基本,就是用线段树维护区间最值,可以算是模板吧…..
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 55129 Accepted Submission(s): 21538Problem Description
很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。 这让很多学生很反感。 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。 Input 本题目包含多组测试,请处理到文件结束。 在每个测试的第一行,有两个正整数 N 和 M ( 1<=N<=200000,1<=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线段树维护区间最值,点修改+区间查询,模板题
代码如下:
#include#include #include #include using namespace std;#define maxn 200001int maxmark[maxn<<2]={ 0},mark[maxn]={ 0};int max(int a,int b){ if (a>b) return a; else return b;}void updata(int now){ maxmark[now]=max(maxmark[now<<1],maxmark[now<<1|1]);}void build(int l,int r,int now){ if (l==r) { maxmark[now]=mark[l]; return; } int mid=(l+r)>>1; build(l,mid,now<<1); build(mid+1,r,now<<1|1); updata(now);}void point_change(int now,int l,int r,int loc,int newmark){ if (l==r) { maxmark[now]=newmark; return; } int mid=(l+r)>>1; if (loc<=mid) point_change(now<<1,l,mid,loc,newmark); else point_change(now<<1|1,mid+1,r,loc,newmark); updata(now);}int section_max(int L,int R,int now,int l,int r){ if (L<=l && R>=r) return maxmark[now]; int mid=(l+r)>>1; int ans=-10000; if (L<=mid) ans=max(ans,section_max(L,R,now<<1,l,mid)); if (R>mid) ans=max(ans,section_max(L,R,now<<1|1,mid+1,r)); return ans; }int main(){ int n,m; while (~scanf("%d%d",&n,&m)) { for (int i=1; i<=n; i++) scanf("%d",&mark[i]); memset(mark,0,sizeof(0)); memset(maxmark,0,sizeof(0)); build(1,n,1); for (int i=1; i<=m; i++) { char command[10]; scanf("%s",&command); if (command[0]=='Q') { int start,end; scanf("%d%d",&start,&end); int answer=section_max(start,end,1,1,n); printf("%d\n",answer); /*for (int j=1; j<=4*n; j++) cout< <<" "; cout<