>Description
在N(1<=N<=100000)个数A1…An组成的序列上进行M(1<=M<=100000)次操作,操作有两种:
(1)1 x y:表示修改A[x]为y;
(1)2 x y:询问x到y之间的最大值。
>Input
第一行输入N(1<=N<=100000),表示序列的长度,接下来N行输入原始序列;接下来一行输入M(1<=M<=100000)表示操作的次数,接下来M行,每行为1 x y或2 x y
>Output
对于每个操作(2)输出对应的答案。
>Sample Input
5
1
2
3
4
5
3
2 1 4
1 3 5
2 2 4
>Sample Output
4
5
保证序列中的所有的数都在longint范围内
>解题思路
线段树模板。
>代码
#include<iostream>
#include<cstdio>
using namespace std;
int n,m,a[100005],z,x[100005],y[100005],t[400005],sum;
void lil(int l,int r,int s) //区间起始,区间终止,线段树中的编号
{
if(l==r)
{
t[s]=a[l];
return;
}
int mid=(l+r)/2;
lil(l,mid,s*2);
lil(mid+1,r,s*2+1);
t[s]=max(t[s*2],t[s*2+1]);
} //构建线段树
void lil2(int l,int r,int s,int tt) //区间起始,区间终止,线段树中的编号,需要改变的值的编号和改变后的值
{
if(l==r)
{
t[s]=a[l];
return;
}
int mid=(l+r)/2;
if(x[tt]<=mid) lil2(l,mid,s*2,tt);
else lil2(mid+1,r,s*2+1,tt);
t[s]=max(t[s*2],t[s*2+1]);
} //1操作(改值)
void lil3(int l,int r,int s,int t1,int t2) //区间起始,区间终止,线段树中的编号,查找的区间的起始,查找的区间的终止
{
if(l==t1&&r==t2)
{
sum=max(sum,t[s]);
return;
}
int mid=(l+r)/2;
if(t1<=mid) lil3(l,mid,s*2,t1,min(mid,t2));
if(t2>mid) lil3(mid+1,r,s*2+1,max(t1,mid+1),t2);
} //2操作(输出)
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
lil(1,n,1);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&z,&x[i],&y[i]);
if(z==1) a[x[i]]=y[i],lil2(1,n,1,i);
else
{
sum=0;
lil3(1,n,1,x[i],y[i]);
printf("%d\n",sum);
}
}
return 0;
}