//①建树 const int MAXM=50000; //定义 MAXM 为线段最大长度 int a[MAXM+5],st[(MAXM<<2)+5]; // a 数组为 main 函数中读入的内容,st 数组为需要查询的数的信息(如和、最值等),树的空间大小为线段最大长度的四倍 void build(int o,int l,int r){ //传入的参数为 o:当前需要建立的结点;l:当前需要建立的左端点;r:当前需要建立的右端点 if(l==r)st[o]=a[l]; //当左端点等于右端点即建立叶子结点时,直接给数组信息赋值 else{ int m=l+((r-l)>>1); // m 为中间点,左儿子结点为 [l,m] ,右儿子结点为 [m+1,r]; build(o << 1,l,m); //构建左儿子结点 build((o << 1)|1,m+1,r); //构建右儿子结点 st[o]=st[o << 1]+st[(o << 1)|1]; //递归返回时用儿子结点更新父节点,此处可进行更新最大值、最小值、区间和等操作 }}int main(){ //在 main 函数中的语句 build(1,1,n);}
//②修改单点 void update(int o,int l,int r,int ind,int ans)//o、l、r为当前更新到的结点、左右端点,ind为需要修改的叶子结点左端点,ans为需要修改成的值; { if(l==r){ //若当前更新点的左右端点相等即到叶子结点时,直接更新信息并返回 st[o]=ans; return; } int m=l+((r-l)>>1); if(ind<=m){ //若需要更新的叶子结点在当前结点的左儿子结点的范围内,则递归更新左儿子结点,否则更新右儿子结点 update(o<<1,l,m,ind,ans); } else{ update((o<<1)|1,m+1,r,ind,ans); } st[o]=max(st[o<<1],st[(o<<1)|1]);//递归回之后用儿子结点更新父节点(此处是区间最大值) }int main() { //在main函数中的语句 update(1,1,n,ind,ans);}
//③查询 int query(int o,int l,int r,int ql,int qr)//ql、qr为需要查询的区间左右端点{ if(ql>r||qr=r) return st[o]; //若当前结点的区间被需要查询的区间覆盖,则返回当前结点的信息 int m=l+((r-l)>>1); int p1=query(o<<1,l,m,ql,qr),p2=query((o<<1)|1,m+1,r,ql,qr); //p1为查询左儿子结点得到的信息,p2为查询右儿子结点得到的信息 return max(p1,p2); //综合两个儿子结点的信息并返回 }{ //main函数中的语句 printf("%d\n",query(1,1,n,a,b));}