[复习]线段树 系列操作I

题目背景
Problem A:系列操作Ⅰ

题目描述
给出序列 a1,a2,…,an (0≤ai≤109) ,有关于序列的两种操作:

  1. ai (1≤i≤n) 加上x(-103≤x≤103)

  2. 求 max{al,al+1,…,ar} (1≤l≤r≤n)

输入格式
第一行包含两个数 n(1≤n≤105)和 m(1≤m≤105),表示序列长度和操作次数。

接下来一行n个数,以空格隔开,表示 a1,a2,…,an。

接下来 m 行,每行为以下两种格式之一。

0 i x ,表示 ai 加上 x 。
1 l r ,求 max{ al,al+1,…,ar }。

输出格式
对于每次询问,输出单独的一行表示答案。

样例数据
输入
5 3
1 2 3 4 5
1 1 5
0 5 -5
1 1 5
输出
5
4

分析:线段树模板

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;

int getint()
{
    int f=1,sum=0;
    char ch;
    for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    if(ch=='-')
    {
        f=-1;
        ch=getchar();
    }
    for(;ch>='0'&&ch<='9';ch=getchar())
        sum=(sum<<3)+(sum<<1)+ch-48;
    return sum*f;
}

const int INF=0x3f3f3f3f;
const int  maxn=100010;
long long a[maxn],treemax[4*maxn];
int n,m;

void buildtree(int num,int l,int r)
{
    if(l==r)
    {
        treemax[num]=a[l];//l和r都是a数组的标号,num才是treemax的
        return;
    }

    int mid=l+r>>1;
    buildtree(num<<1,l,mid);
    buildtree(num<<1|1,mid+1,r);//mid记得+1
    treemax[num]=max(treemax[num<<1],treemax[num<<1|1]);
}

void change(int num,int l,int r,int findnum,int x)
{
    if(l==r)
    {
        treemax[num]+=x;
        return;
    }

    int mid=l+r>>1;
    if(mid>=findnum)//注意等号
        change(num<<1,l,mid,findnum,x);
    else
        change(num<<1|1,mid+1,r,findnum,x);//注意+1和等号的位置

    treemax[num]=max(treemax[num<<1],treemax[num<<1|1]);//记得更新数组
}

long long check(int num,int l,int r,int ll,int rr)
{
    if(ll<=l&&rr>=r)
        return treemax[num];

    int mid=l+r>>1,a=-INF,b=-INF;//注意a、b赋值
    if(ll<=mid)
        a=check(num<<1,l,mid,ll,rr);
    if(rr>mid)
        b=check(num<<1|1,mid+1,r,ll,rr);

    return max(a,b);
}

int main()
{
    freopen("xlcz.in","r",stdin);
    freopen("xlcz.out","w",stdout);

    n=getint();m=getint();
    for(int i=1;i<=n;++i)
        a[i]=getint();

    buildtree(1,1,n);

    int bj,x,y;
    long long ans;
    while(m--)
    {
        bj=getint();x=getint();y=getint();
        if(bj==0)
            change(1,1,n,x,y);
        else
        {
            ans=check(1,1,n,x,y);
            cout<<ans<<'\n';
        }
    }

    return 0;
}

本题结。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值