[编程题] 最高分是多少

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 64M,其他语言128M

老师想知道从某某同学当中,分数最高的是多少,现在请你编程模拟老师的询问。当然,老师有时候需要更新某位同学的成绩.

输入描述:
输入包括多组测试数据。
每组输入第一行是两个正整数N和M(0 < N <= 30000,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。

输出描述:
对于每一次询问操作,在一行里面输出最高成绩.

输入例子1:
5 7
1 2 3 4 5
Q 1 5
U 3 6
Q 3 4
Q 4 5
U 4 5
U 2 9
Q 1 5

输出例子1:
5
6
5
9

思路:作为打过ACM的学子看到此题第一反应就是线段树了,结果一直不过。在看了答案和其他博客后才知到题目竟然还暗藏陷阱。。。重点还发现了此题竟然暴力也能通过。。。(看来这是打ACM的后遗症了,哈哈哈。。。)
解法参考:https://blog.csdn.net/flowingfog/article/details/76945183
https://www.cnblogs.com/heling-android/p/6612189.html

scanf忽略换行符参考:https://blog.csdn.net/qq_33508523/article/details/88089631
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=3*1e4+5;//运行超时的话要注意此处空间是否够大!
 4 struct node
 5 {
 6     int l,r,sum,ma;
 7 }no[N*4];//这里的大小已乘4,所以设定N值时不用乘以4
 8 
 9 void build(int id,int l,int r)//建树
10 {
11     no[id].l=l;
12     no[id].r=r;
13     no[id].sum=no[id].ma=0;
14     if (l==r)
15         return;
16     int mid=(l+r)/2;
17     build(id*2,l,mid);
18     build(id*2+1,mid+1,r);
19 }
20 
21 void change(int id,int v,int val)//节点赋值
22 {
23     if (no[id].l==v&&no[id].r==v)//判断条件写错会导致死循环!
24     {
25         no[id].sum=no[id].ma=val;
26         return;//不要漏掉return!!
27     }
28     int mid=(no[id].l+no[id].r)/2;
29     if (v<=mid)
30         change(id*2,v,val);
31     else
32         change(id*2+1,v,val);
33     no[id].sum=no[id*2].sum+no[id*2+1].sum;
34     no[id].ma=max(no[id*2].ma,no[id*2+1].ma);
35 }
36 
37 int qmax(int id,int l,int r)//区间最大值
38 {
39     if (l==no[id].l&&no[id].r==r)
40     {
41         return no[id].ma;
42     }
43     int mid=(no[id].l+no[id].r)/2;
44     if (r<=mid)
45         return qmax(id*2,l,r);
46     else if (l>mid)
47         return qmax(id*2+1,l,r);
48     else
49         return max(qmax(id*2,l,mid),qmax(id*2+1,mid+1,r));
50 }
51 
52 int main()
53 {
54     freopen("E:\ACM\test\input.txt","r",stdin);
55     int n,m,b,c,val;
56     char q;
57     while (scanf("%d%d",&n,&m)!=EOF)//n为学生数,m为操作数
58     {
59         build(1,1,n);//建立线段树
60         for (int i=1;i<=n;i++)//初始化分数
61         {
62             scanf("%d",&val);
63             change(1,i,val);
64         }
65         for (int i=0;i<m;i++)
66         {
67             scanf("
%c%d%d",&q,&b,&c);//此占位符甚妙,否则scanf会读入换行符
68             switch (q)//q为操作类型
69             {
70                 case 'U':
71                     change(1,b,c);//更改分数
72                 break;
73                 case 'Q':
74                     int bb=min(b,c), cc=max(b,c);//注意要确保区间两端的大小正确
75                     printf("%d
",qmax(1,bb,cc));//求区间最大分数
76                 break;
77             }
78         }
79     }
80 
81  return 0;
82 }


原文地址:https://www.cnblogs.com/hemeiwolong/p/12291418.html