线段树模板

来源:互联网 发布:java调dll内存泄露 编辑:程序博客网 时间:2024/05/18 15:56


#include<cstdio>#include<algorithm>using namespace std;#define L o<<1#define R (o<<1)|1struct Node{int l,r,sum,Max,Min;}Tree[1000<<2];void PushUp(int o){Tree[o].sum = Tree[o*2].sum + Tree[o*2+1].sum;Tree[o].Max = max(Tree[o*2].Max,Tree[o*2+1].Max);Tree[o].Min = min(Tree[o*2].Min,Tree[o*2+1].Min);}void Build(int o,int l,int r)//          建树,l相当于 1 r相当于 4 ,即初始的 {//首先记录l和r的值 Tree[o].l = l;Tree[o].r = r;if (l == r)//到达最底层,递归终止{int t;scanf ("%d",&t);//输入数据 Tree[o].sum = Tree[o].Max = Tree[o].Min = t;//更新节点数据 return;}int mid = (l+r) >> 1;//找到中间节点 Build(o*2 , l , mid);//递归建左子树 Build(o*2+1 , mid+1 , r);//递归建右子树 PushUp(o);//更新当前节点的值 }void UpDate(int o,int l,int r,int x,int y)//把x节点更新为y{if (l == r)//递归结束{Tree[o].Max = Tree[o].Min = Tree[o].sum = y;//精确找到了节点,更新 return;}int mid = (l+r) / 2;//找到中间位置if (x <= mid)UpDate(o*2,l,mid,x,y);//找左子树 elseUpDate(o*2+1,mid+1,r,x,y);//找右子树 PushUp(o);//更新当前节点 }int QuerySum(int o,int l,int r,int x,int y)//查找x到y的和 {if (l == x && r == y)//如果恰好是当前节点,就返回 {return Tree[o].sum;}int mid = (l + r) / 2;if (mid >= y)//全在左边 return QuerySum(o*2,l,mid,x,y);else if (x > mid)//全在右边 return QuerySum(o*2+1,mid+1,r,x,y);    //因为 x 判断时不包含 ‘= ‘所以 mid+1 else//一半在左一半在右 return QuerySum(o*2,l,mid,x,mid) + QuerySum(o*2+1,mid+1,r,mid+1,y);}int QueryMax(int o,int l,int r,int x,int y){if(l == x&&r==y){return Tree[o].Max ;}int mid=(l+r)/2;if(mid>=y)return QueryMax(o*2,l,mid,x,y);else if(x>mid)return QueryMax(o*2+1,mid+1,r,x,y);elsereturn max(QueryMax(o*2,l,mid,x,mid),QueryMax(o*2+1,mid+1,r,mid+1,y));}int main(){int n;scanf ("%d",&n);Build(1,1,n);      //初始节点记为 1  左节点也为 1 //UpDate(1,1,n,2,7);printf ("%d\n",QuerySum(1,1,n,2,4));printf ("%d\n",QueryMax(1,1,n,2,4));return 0;}


原创粉丝点击