最大值【线段树】

>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;
}

你可能感兴趣的:(线段树)