HDU - 1754 - I Hate It(区间最值,线段树)

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

 

Sample Output

 
5 6 5 9

Hint

Huge input,the C function scanf() will work better than cin  

Author

linle

 

Source

2007省赛集训队练习赛(6)_linle专场

树状数组 区间最值了解一下, 有点没看懂。

https://blog.csdn.net/u010598215/article/details/48206959

哎 还是脑子不好使。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=3e5;
int a[maxn],c[maxn];//因为c[y]表示的是[y,y-lowbit(y)+1]的最大值
int n,m;
int lowbit(int i)
{
	return i&(-i);
}
void update(int i,int val)
{
	a[i]=val;
	while(i<=n)
	{
		c[i]=max(c[i],val);
		i+=lowbit(i);
	}
}
int query(int x,int y)
{
	int ans=a[y];//上边界
	while(x!=y)
	{
		for(y-=1;y-lowbit(y)>=x;y-=lowbit(y))
		{
			ans=max(ans,c[y]);//注意计算区间,不要跨区间 
		}
		ans=max(ans,a[y]);//下边界 
	 } 
	return ans;
}
int main()
{
	int i,j,x,y,ans;
	char cc;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		memset(c,0,sizeof(c));
		for(i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			update(i,a[i]);
		}
	
		for(i=1;i<=m;i++)
		{
			getchar();
			scanf("%c",&cc);
			if(cc=='Q')
			{
				scanf("%d%d",&x,&y);
				ans=query(x,y);
				printf("%d\n",ans);
			}else if(cc=='U')
			{
				scanf("%d%d",&x,&y);
				update(x,y);
			 } 
		}
	}return 0;
}

直接利用 线段树 模板题

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
int sum[200500<<2];//<<代表  左移 两位 相当于 *2^2
void PushUp(int node)//更新最大值
{
	sum[node]=max(sum[node*2],sum[node*2+1]);
 } 
 void Build(int l,int r,int node)//建树 
 {
 	if(l==r) 
	 {
	 	scanf("%d",&sum[node]);
	 	return ;
	  } 
	int m=(l+r)/2;
	Build(l,m,node*2);
	Build(m+1,r,node*2+1);
	PushUp(node);//更新 
 }
 void UpData(int p,int add,int l,int r,int node)//更新节点 
 {
 	if(l==r)
 	{
 		sum[node]=add;
 		return ;
	 }
	 int m=(l+r)/2;
	 if(p<=m)//p当前线段树根节点下标 
	 UpData(p,add,l,m,node*2); 
	 else 
	 UpData(p,add,m+1,r,node*2+1);
	 PushUp(node);
 }
 int Query(int L,int R,int l,int r,int node)//求最大值 
 {
 	if(L<=l&&R>=r)
	 return sum[node];
	int m=(l+r)/2;
	int ans1=0,ans2=0;
	if(L<=m)
	ans1=Query(L,R,l,m,node*2);
	if(R>m)
	ans2=Query(L,R,m+1,r,node*2+1);
	return max(ans1,ans2); 
 }
 int main()
 {
 	int n,m,a,b;
 	while(scanf("%d%d",&n,&m)!=EOF)
 	{
 		Build(1,n,1);
 		char c;
 		getchar();	
 		while(m--)
 		{
 			scanf("%c",&c);
 			scanf("%d%d",&a,&b);
 			if(c=='Q')
 			printf("%d\n",Query(a,b,1,n,1));
 			else if(c=='U')
 			UpData(a,b,1,n,1);
 			getchar();
		 }
	 }return 0;
 }

猜你喜欢

转载自blog.csdn.net/qq_40046426/article/details/81171911