线段树——I hate it
2016-03-08 08:08
281 查看
[align=left][问题描述][/align]
很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。
这让很多学生很反感。
不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。
[align=left][输入][/align]
本题目包含多组测试,请处理到文件结束。
在每个测试的第一行,有两个正整数 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。
[align=left][输出][/align]
对于每一次询问操作,在一行里面输出最高成绩。
[align=left][输入样例][/align]
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
[align=left][输出样例][/align]
5
6
5
9
提供原程序和具体分析如下:
提供原程序前,先进行如下几点说明(源程序的风格):
•maxn是题目给的最大区间,而节点数要开4倍,确切的来说节点数要开大于maxn的最小2x的两倍
•lson和rson分辨表示结点的左儿子和右儿子,由于每次传参数的时候都固定是这几个变量,所以可以用预定于比较方便的表示
•以前的写法是另外开两个个数组记录每个结点所表示的区间,其实这个区间不必保存,一边算一边传下去就行,只需要写函数的时候多两个参数,结合lson和rson的预定义可以很方便
•PushUP(int rt)是把当前结点的信息更新到父结点
•PushDown(int rt)是把当前结点的信息更新给儿子结点
•rt表示当前子树的根(root),也就是当前所在的结点
很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。
这让很多学生很反感。
不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。
[align=left][输入][/align]
本题目包含多组测试,请处理到文件结束。
在每个测试的第一行,有两个正整数 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。
[align=left][输出][/align]
对于每一次询问操作,在一行里面输出最高成绩。
[align=left][输入样例][/align]
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
[align=left][输出样例][/align]
5
6
5
9
提供原程序和具体分析如下:
提供原程序前,先进行如下几点说明(源程序的风格):
•maxn是题目给的最大区间,而节点数要开4倍,确切的来说节点数要开大于maxn的最小2x的两倍
•lson和rson分辨表示结点的左儿子和右儿子,由于每次传参数的时候都固定是这几个变量,所以可以用预定于比较方便的表示
•以前的写法是另外开两个个数组记录每个结点所表示的区间,其实这个区间不必保存,一边算一边传下去就行,只需要写函数的时候多两个参数,结合lson和rson的预定义可以很方便
•PushUP(int rt)是把当前结点的信息更新到父结点
•PushDown(int rt)是把当前结点的信息更新给儿子结点
•rt表示当前子树的根(root),也就是当前所在的结点
#include <cstdio> #include <algorithm> using namespace std; #define lson l , m , rt << 1 //用lson来代替三个参数:l,m,rt*2,注意rt<<1就是rt*2; #define rson m + 1 , r , rt << 1 | 1 //同上,rt<<1|1,相当于rt*2+1; const int maxn =222222; int MAX[maxn<<2]; //二进行向右移两位相当于maxn*4; void PushUP(int rt){ //用于向上回溯 MAX[rt]= max(MAX[rt<<1] , MAX[rt<<1|1]); //选择左右孩子中的较大者 } void build(int l,int r,int rt){ //建立线段树 if(l == r){ scanf("%d",&MAX[rt]); //至叶结点时读数 return; } int m =(l + r)>>1; build(lson); //线段树分为左孩子 build(rson); //线段树分为右孩子 PushUP(rt); //向上回溯 } void update(int p,int sc,int l,int r,int rt){ if(l == r){ MAX[rt]= sc; return; } int m =(l + r)>>1; if(p <= m) update(p , sc , lson); else update(p , sc , rson); PushUP(rt); } int query(int L,int R,int l,int r,int rt){ if(L <= l && r <= R){ return MAX[rt]; } int m =(l + r)>>1; int ret =0; if(L <= m) ret = max(ret , query(L , R , lson)); if(R > m) ret = max(ret , query(L , R , rson)); return ret; } int main(){ int n , m; while(~scanf("%d%d",&n,&m)){ build(1 , n , 1); while(m --){ char op[2]; int a , b; scanf("%s%d%d",op,&a,&b); if(op[0]=='Q')printf("%d\n",query(a , b , 1 , n , 1)); else update(a , b , 1 , n , 1); } } return 0; }
相关文章推荐
- 程序中写数据到文件
- 互联网面试总结(三) : 算法
- 《数据结构》顺序栈
- ATEN宏正盛装出席Infocomm China 2016
- 互联网面试总结(二) : 概述题
- HTML 5 视频使用
- 正则表达式
- 前端性能优化--能用css的地方尽量不要用js
- [leetcode] 167. Two Sum II - Input array is sorted 解题报告
- 软件第二次作业
- 作业
- oracle GROUPING函数
- Linux用户和用户组基本概念
- andriod VideoView
- rcnn学习笔记:Rich feature hierarchies for accurate object detection and semantic segmentation
- HDU 2105 The Center of Gravity (水题)
- huffman树_优先权队列
- js和jquery获取父级元素、子级元素、兄弟元素的方法{转}
- pat1057 stack
- pat1057 stack