线段数例题3

区间极大值2.0 

有一个长度为n的整数数列a。
现在有m个操作,操作的格式有两种:
“1 x y”,表示修改,将数列第x个数a[x]改为a[x]+y;
“2 x y” , 表示询问,询问第x个数到第y个数间,最大的一个数是多少。

输入格式:

第一行,两个整数n和m
第二行,n个空格间隔的整数,表示数列a
接下来m行,每行三个整数k,x和y,表示一个操作,k=1表示修改,k=2表示询问

输出格式:

若干行,每行对应一个询问的结果

样例输入:
7 5
-1 6 5 3 4 9 7
1 4 5
2 2 6
2 1 3
1 6 -8
2 2 6  
样例输出:
9
6
8

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;

struct node
{
    int a,b,l,r,Max;
};
node tree[200001];
int m,n;
int a[100010],tot=0;
void build(int x,int y)
{
    int now=++tot;
    tree[now].a=x;
    tree[now].b=y;
    tree[now].Max=0;
    if(x<y)
    {
        tree[now].l=tot+1;
        build(x,(x+y)/2);
        tree[now].r=tot+1;
        build((x+y)/2+1,y);
        tree[now].Max=max(tree[tree[now].l].Max,tree[tree[now].r].Max);
    }
    else tree[now].Max=a[x];
}
void change(int p,int k,int d)
{
        if(tree[p].a<=k&&k<=tree[p].b)
        {
      if(tree[p].a==tree[p].b){tree[p].Max=a[k]+d;  return;  }

      int Lson=tree[p].l,  Rson=tree[p].r;
      if(Lson)change(Lson,k,d);
      if(Rson)change(Rson,k,d);
      tree[p].Max=max(tree[Lson].Max,tree[Rson].Max);
      }
}

int getmax(int p,int x,int y)
{
    if(x<=tree[p].a&&tree[p].b<=y) return tree[p].Max;
    int lmax=0,rmax=0,mid=(tree[p].a+tree[p].b)/2;
    if(x<=mid) lmax=getmax(tree[p].l,x,y);
    if(y>mid) rmax=getmax(tree[p].r,x,y);
    return max(lmax,rmax);
}

int main()
{
    memset(a,0,sizeof(a));
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d ",&a[i]);
    }
    build(1,n);
    while(m--)
    {
        int z,x,y;
        scanf("%d %d %d",&z,&x,&y);
        if(z==1)
        {
            change(1,x,y);
        }
        if(z==2)
          printf("%d\n",getmax(1,x,y));
    }
}
原文地址:https://www.cnblogs.com/wanghaixv/p/8497099.html