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
对于每一次询问操作,在一行里面输出最高成绩。
SampleInput
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
SampleOutput
5
6
5
9
Hint
Huge input,the C function scanf() will work better than cin
可以用一个结构体,存下每个线段的左右端点,这样更好理解
typedef struct tree
{
int data;
int left;
int right;
}tree;
一般线段树每个线段存的是该线段区间的权重,我们把他改成该区间的最大值,这就是解题思路。
注意,如果从下标为0的位置开始读数组,那么i点的左右孩子应该为i * 2+1和 i *2+2。
ac代码
#include<stdio.h>
#include<algorithm>
#include<stdlib.h>
using namespace std;
const int ssum=2e6+5;
typedef struct tree
{
int data;
int left;
int right;
}tree;
int in[ssum];
tree T[ssum*2];
int Builtree(int i,int l,int r)
{
T[i].left=l;T[i].right=r;
if(l==r)
{
T[i].data=in[l];
return T[i].data;
}
int m=(l+r)>>1;
Builtree(i*2,l,m);
Builtree(i*2+1,m+1,r);
T[i].data=max(T[i*2].data,T[i*2+1].data);
return T[i].data;
}
void update(int a,int b,int i)
{
if(T[i].right==T[i].left)
{
T[i].data=b;
return;
}
if(a<=T[i*2].right)
{
update(a,b,i*2);
T[i].data=max(T[i].data,T[i*2].data);
}
if(a>=T[i*2+1].left)
{
update(a,b,i*2+1);
T[i].data=max(T[i].data,T[i*2+1].data);
}
}
int ans=0;
int qqq(int l,int r,int i)
{
if(T[i].left>=l&&T[i].right<=r)//包含在区间内
{
ans=max(T[i].data,ans);//若i==n就需要这句代码,不然就wan
return T[i].data;
}
if(T[i].right<l||T[i].left>r)//在区间外
{
return 0;
}
if(T[i*2].right>=l) ans=max(ans,qqq(l,r,i*2));//与该区间的左区间有交集即左区间的右边界大于l
if(T[i*2+1].left<=r) ans=max(ans,qqq(l,r,i*2+1));//与该区间的右区间有交集
return ans;
}
int main()
{
int n,m,i,a,b,c;
char s[10];
while(~scanf("%d%d",&n,&m))
{
i=1;
while(i<=n)
{
scanf("%d",&in[i]);
i++;
}
Builtree(1,1,n);
while(m--)
{
scanf("%s%d%d",s,&a,&b);
if(s[0]=='U')
{
update(a,b,1);
}
if(s[0]=='Q')
{
ans=0;
qqq(a,b,1);
printf("%d\n",ans);
}
}
}
}
博客围绕学生成绩查询与更新问题展开,需处理多组测试数据。输入包含学生数目、操作数目、初始成绩及操作指令,操作分查询和更新。解题思路是用结构体存线段端点,将线段树存的权重改为区间最大值,还给出了数组下标与左右孩子的关系及AC代码。
535

被折叠的 条评论
为什么被折叠?



