hdu1754 I Hate It

来源:互联网 发布:厦门市公安局网络公章 编辑:程序博客网 时间:2024/05/18 01:32
Problem Description
很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。
这让很多学生很反感。

不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。
 

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 61 2 3 4 5Q 1 5U 3 6Q 3 4Q 4 5U 2 9Q 1 5
 

Sample Output
565

9

思路:模板题,直接套模板,线段树入门题目。主要就是点更新与区间查询。注意输入数据尽量用scanf!

代码:

#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int maxn=200010;struct node{int mark;int max;}stu[4*maxn];void build(int l,int r,int i)//i为结构体数组的下标{stu[i].max=0;//给每个节点赋初值 if(l==r){scanf("%d",&stu[i].mark);stu[i].max=stu[i].mark;//当最后线段等于点的时候赋初值。最底层!!,递归结束,一层一层的结束 return ;}int mid=(l+r)/2;build(l,mid,i<<1);//zuo build(mid+1,r,(i<<1)+1);//youstu[i].max=max(stu[i<<1].max,stu[(i<<1)+1].max); //递归,顾名思义就是自下而上,不断地从下往上更新答案,最后退出的肯定是根节点 i=1 } void update(int l,int r,int i,int x,int y)//i数组下标,x待查数据下标,y待查数据的变化量 {if(l==r){//说明不断二分找到了x,就是l==r==x;stu[i].mark=y;stu[i].max=stu[i].mark;return ; } int mid=(l+r)/2;//找到中间 if(x<=mid)update(l,mid,i<<1,x,y);elseupdate(mid+1,r,(i<<1)+1,x,y);stu[i].max=max(stu[i<<1].max,stu[(i<<1)+1].max);}int querymax(int l,int r,int i,int x,int y){if(x<=l&&y>=r) return stu[i].max;//如果覆盖就选择区间内的最大值 int mid=(l+r)/2;//这个地方要注意,要把x,y分开与mid比较,这样就可以通过不断地递归,将左右两端都求解出来 int Max=0;if(x<=mid)//如果x在左,这是一种特殊情况,y不能确定,但是x不在左,那x肯定在右,y也必定在右 Max=max(Max,querymax(l,mid,i<<1,x,y));if(y>mid)Max=max(Max,querymax(mid+1,r,(i<<1)+1,x,y));return Max;}int main(){int n,m;while(scanf("%d %d",&n,&m)!=EOF){//习惯了用cin scanf的时候忘记写EOF build(1,n,1);while(m--){//getchar();char s;cin>>s;if(s=='Q'){int x,y;scanf("%d %d",&x,&y);int ans=querymax(1,n,1,x,y);cout<<ans<<endl;}if(s=='U'){int x,y;scanf("%d %d",&x,&y);update(1,n,1,x,y);}}}return 0;} 


0 0
原创粉丝点击