题目 2447: [信息学奥赛一本通-T1541]数列区间最大值(线段树)

题目 2447: 信息学奥赛一本通-T1541数列区间最大值

菜鸟生成记(67)

线段树求区间最大值

不过这个判题机有点儿坑,scanf,printf都过不了,必须"开挂"才行

AC代码(输入输出加速挂)

#include<stdio.h>
#define N 100100
#define max(x,y) x>y?x:y
#define inf ((1<<32)-1) //int最大值 
int arr[N];
int tree[4*N];//4倍空间 
int n,m;
void bulid_t(int rt ,int start ,int end)//构建线段树 
{
	if(start == end)
	{//线段树叶子结点赋值
	//叶子结点最大值就是自己 
		tree[rt]=arr[start];
	}
	else
	{	
		int mid = (start+end) >> 1;//右移1位(除2),快一些 
		int left_son  = (rt<<1) + 1;//2*rt+1
		int right_son = (rt<<1) + 2;//2*rt+2 
		bulid_t(left_son  ,start ,mid);//找左儿子,同时给之赋值 
		bulid_t(right_son ,mid+1 ,end);//找右儿子,同时给之赋值 
		//父节点等于左右儿子中的最大值 
		tree[rt] = max(tree[left_son] , tree[right_son]);
	}	
}
int query_t(int rt ,int start ,int end ,int L ,int R)//查询[L - R]最大值 
{
	if(end < L || start > R)
	{//当前区间不在查询区间内,区间和返回-inf; 
		return -inf;
	}
	else if(start >= L && end <= R)
	{//当前区间被查询区间全部包括,区间和返回当前结点值;
		return tree[rt];
	}
	else if(start == end)
	{//当前区间为一个点,区间和返回结点值 
		return tree[rt];
	}
	else//当前区间一部分属于查询区间,另一部分不属于; 
	{
		int mid = (start + end) >> 1;
		int left_son  = (rt<<1) + 1;//2*rt+1
		int right_son = (rt<<1) + 2;//2*rt+2 
		int left_val = query_t(left_son , start , mid , L , R);
		int right_val= query_t(right_son, mid+1 , end , L , R);
		return max(left_val , right_val);//返回左右子区间最大值 
	}
}
int read()//输入挂 加快输入 
{
    char ch=' ';
    int ans=0;
    while(ch<'0' || ch>'9')
        ch=getchar();
    while(ch<='9' && ch>='0')
    {
        ans=ans*10+ch-'0';
        ch=getchar();
    }
    return ans;
}
void out(int a)//输出挂 加快输出 
{
    if(a > 9)
    {
        out(a/10);
    }
    putchar(a%10 + '0');
}
/*
10 2
3 2 4 5 6 8 1 2 9 7
1 4
3 8
*/
int main()
{
	n=read();//输入挂 
	m=read();//输入挂 
	for(int i=0;i<n;++i)
	arr[i]=read();
	bulid_t(0,0,n-1);//构造线段树 
	for(int i=0;i<m;++i)
	{
		int a,b,ans;
		a=read();//输入挂 
		b=read();//输入挂 
		//因为数组arr下标从0开始,所以左右边界都要-1 
		ans=query_t(0 ,0 ,n-1 ,a-1 ,b-1);
		out(ans);//输出挂 
		putchar('\n');
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值