线段数例题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)); } }