时间限制: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 }