【线段树模板】

来源:互联网 发布:阿里云服务器地域选择 编辑:程序博客网 时间:2024/06/05 18:24
/*    一个节点下标为o,它的左孩子的下标等于 o*2 ,   右孩子等于o*2+1,左孩子区间【1,o*2】,右孩子区间【o*2+1,n】 */#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)//建树,o为下标,l,r为区间 ,用递归首先想出来递归结束条件 {    //首先记录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);      //找左子树     else        UpDate(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);    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)//查找x到y之间的最大值 {    if(l==x&&r==y)    {        return Tree[o].Max ;    }    int mid=(l+r)>>1;    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);             else return max(QueryMax(o*2,l,mid,x,mid),QueryMax(o*2+1,mid+1,r,mid+1,y));}int QueryMin(int o,int l,int r,int x,int y)//查找x到Y之间的最小值 {    if(l==x&&r==y)    {        return Tree[o].Min ;    }    int mid=(l+r)>>1;    if(mid>=y)    {        return QueryMin(o*2,l,mid,x,y);    }    else if(x>mid)         return QueryMin(o*2+1,mid+1,r,x,y);             else return min(QueryMin(o*2,l,mid,x,mid),QueryMin(o*2+1,mid+1,r,mid+1,y));}int main(){    int n,m;    scanf ("%d",&n);    Build(1,1,n);//  UpDate(1,1,n,2,7);    printf ("%d\n",QuerySum(1,1,n,2,4));    printf ("%d\n",QueryMax(1,1,n,2,4)-QueryMin(1,1,n,2,4));//  printf ("%d\n",QueryMin(1,1,n,2,4));    return 0;}
原创粉丝点击