下面是NOS神犇的简介:
{
在代码前先介绍一些我的线段树风格:
maxn是题目给的最大区间,而节点数要开4倍,确切的来说节点数要开大于maxn的最小2x的两倍
lson和rson分辨表示结点的左儿子和右儿子,由于每次传参数的时候都固定是这几个变量,所以可以用预定于比较方便的表示
以前的写法是另外开两个个数组记录每个结点所表示的区间,其实这个区间不必保存,一边算一边传下去就行,只需要写函数的时候多两个参数,结合lson和rson的预定义可以很方便
PushUP(int rt)是把当前结点的信息更新到父结点
PushDown(int rt)是把当前结点的信息更新给儿子结点
rt表示当前子树的根(root),也就是当前所在的结点
}
我是看了他的博客才会的超级简单的线段树...
http://www.notonlysuccess.com/?p=978
当然还是要继续学习的!加油!
#include<stdio.h>
#include<string.h>
#define MAXN 200005
int max[MAXN<<2];
int mx( int a,int b ){ return a>b?a:b; }
void PushUp( int root ){
max[root]=mx( max[root<<1],max[root<<1|1] );
}
void build( int l,int r,int root )
{
if( l==r ){
scanf( "%d",&max[root] );
return ;
}
int m=(l+r)/2;
build( l,m,root<<1 );
build( m+1,r,root<<1|1 );
PushUp(root);
}
void update( int at,int value,int L,int R, int root )
{
if( L==R )
{
max[root]=value;
return ;
}
int m=(L+R)/2;
if( at<=m )update( at,value,L,m,root<<1 );
else update( at,value,m+1,R,root<<1|1 );
PushUp(root);
return ;
}
int query( int l,int r,int L,int R,int root )
{
if( l<=L && R<=r )
return max[root];
int res=0;
int m=(L+R)/2;
if( l<=m )res=mx( res,query(l,r,L,m,root<<1) );
if( r>m )res=mx( res,query(l,r,m+1,R,root<<1|1) );
return res;
}
int main()
{
int N,Q,a,b,i;
char com;
while( ~scanf( "%d%d",&N,&Q ) )
{
build(1,N,1);
for( i=1;i<=Q;i++ )
{
scanf( "\n%c%d%d",&com,&a,&b );
if( com=='Q' )
printf( "%d\n",query(a,b,1,N,1) );
else
update( a,b,1,N,1 );
}
}
return 0;
}