链接网址:http://www.tyvj.cn/Problem_Upload.asp?id=1039
#include <iostream>
#include <cstdio>
using namespace std;
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
// N为最大结点个数
#define N 100005
struct LineTree // 线段的结构
{
int l,r; // 线段的左右边界
int ans, maxk, mink; // 需要计算的结果
LineTree *lchild,*rchild; //指向左右子树的指针
};
int pos = 0; //建立线段树时用来确定对应的线段
LineTree mem[3*N]; //保存所有的线段
int num[N]; //各个结点的初始值
LineTree *CreateTree(int a,int b) //建立区间为[a,b]的线段
{
int mid;
LineTree *s=&mem[pos++];
s->l=a;
s->r=b;
if(a + 1 < b) //不是叶子结点线段
{
mid=(a+b)/2;
s->lchild=CreateTree(a,mid);
s->rchild=CreateTree(mid,b);
}
return s;
}
void update(LineTree *s,int a,int b) //将点a的值增加或者减少b
{
if(s->l == a && s->l + 1 == s->r) //是叶子结点
{
s->ans = b; s->mink = b;
s->maxk = b;
//修改叶子结点
return;
}
if(a < s->lchild->r) update(s->lchild,a,b); //递归修改左边
else if(a >= s->rchild->l) update(s->rchild,a,b); //递归修改右边边
s->maxk = max(s->lchild->maxk,s->rchild->maxk); //修改中间结点
s->mink = min(s->lchild->mink,s->rchild->mink);
}
int search(LineTree *s,int a,int b,int f)
{
if(s->l == a && s->r - 1 == b && f == 1) return s->maxk; //查询区间[a,b]的最大值
if(s->l == a && s->r - 1 == b && f == 0) return s->mink; //查询区间[a,b]的最小值
int mid=(s->l+s->r)/2;
if(b < mid) return search(s->lchild,a,b,f); //在左边
else if(a>=mid) return search(s->rchild,a,b,f); //在右边
else //左右都有
{
if( f ) return max(search(s->lchild,a,mid-1,f),search(s->rchild,mid,b,f)) ;
else return min(search(s->lchild,a,mid-1,f),search(s->rchild,mid,b,f)) ;
}
}
int main()
{
int n, q;
LineTree * s ;
scanf("%d%d",&n, &q);
s = CreateTree(1,n+1);
for( int i = 1; i <= n; i ++ )
{
int b;
scanf("%d",&b);
update(s,i,b);
}
for( int i = 0; i < q; i ++ )
{
int a,b,t;
scanf("%d%d%d",&t,&a,&b);
if(t==2) update(s,a,b);
else printf("%d\n",search(s,a,b,0) ) ;
}
return 0;
}