hdu1754 求区间最值 线段树 树状数组

题意不用解释了

线段树:

#include <cstdio>
#include <algorithm>
using namespace std;
 
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 222222;
int MAX[maxn<<2];
void PushUP(int rt) {
	MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]);
}
void build(int l,int r,int rt) {
	if (l == r) {
		scanf("%d",&MAX[rt]);
		return ;
	}
	int m = (l + r) >> 1;
	build(lson);
	build(rson);
	PushUP(rt);
}
void update(int p,int add,int l,int r,int rt) {
	if (l == r) {
		MAX[rt] = add;
		return ;
	}
	int m = (l + r) >> 1;
	if (p <= m) update(p , add , lson);
	else update(p , add , rson);
	PushUP(rt);
}
int query(int L,int R,int l,int r,int rt) {
	if (L <= l && r <= R) {
		return MAX[rt];
	}
	int m = (l + r) >> 1;
	int ret = 0;
	//递归调用每回求最值 
	if (L <= m) ret = max(ret , query(L , R , lson));
	if (R > m) ret = max(ret , query(L , R , rson));
	return ret;
}
int main() {
	int n , m;
	while (~scanf("%d%d",&n,&m)) {
		build(1 , n , 1);
		while (m --) {
			char op[2];
			int a , b;
			scanf("%s%d%d",op,&a,&b);//此处用%s 避免一个字符错误 
			if (op[0] == 'Q') printf("%d\n",query(a , b , 1 , n , 1));
			else update(a , b , 1 , n , 1);
		}
	}
	return 0;
}


树状数组

#include<iostream>
#include<cstring>
#include <cstring>
#define N 200001
using namespace std;
int num[N],p[N];
int n;
int lowbit(int t)
{
	return t&(-t);
}
void change()//找最大值初始化
{
    int i,j;
    for(i = 1;i <= n;i ++)
    {
        p[i] = num[i];
        for(j = 1;j < lowbit(i);j <<= 1)
		//找比i小的数但又在lowbit(i)+1到i这个区间上的数更新p数组
        {
			p[i]=max(p[i],p[i-j]);//j是以2倍的速度增长
        }
     }
}
void insert(int t,int sore)
{
    num[t] = sore;
    while(t <= n)
    {
        if(sore > p[t])
        p[t] = sore;
        else
        break;
        t += lowbit(t);
    }
}
int getmax(int l,int r)//找最大值
{
    int ans = num[r];
    for(;;)
    {
        ans=max(ans,num[r]);//跟r位置上的数字比较
        if(l == r) break;
        for(r = r-1;r-l >=lowbit(r);r -= lowbit(r))
        {
            if(ans < p[r])
            ans = p[r];
        }
    }//r自减1,判断r-lowbit(r)和l之间的关系如果l在区间内就不能减了而是继续循环
    return ans;//如果l比r-lowbit(r)小的话,就可以之间判断ans和p[r]的最值了。
}
int main()
{
    int m,i,id,sd,max;
    char str[2];
    while(scanf("%d%d",&n,&m)!=EOF)
    {
       	memset(p,0,sizeof(p));
       	for(i = 1;i <= n;i ++)
		scanf("%d",&num[i]);
		//scanf("%d%*c",&num[i]);
		//若此处是这个%*c是为了消除后面的回车字符,后面就可以改为输入一个字符 
        change();
        for(i = 1;i <= m;i ++)
        {
            scanf("%s%d%d%*c",str,&id,&sd);
            if(str[0] == 'Q')
            {
                max = getmax(id,sd);
                printf("%d\n",max);
            }
            else if(str[0] == 'U')
            {
                insert(id,sd);
            }
        }
	}
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值