简单的线段树

来源:互联网 发布:centos配置rsyslog 编辑:程序博客网 时间:2024/06/04 19:43

前言

线段树想必大家再熟悉不过了,说实话敲线段树的模板还是很享受的(温馨提示:不要被数据结构所驾驭了)。
这里,蒟蒻我就简要说一下鄙人的线段树的一些简单功能:支持单点、区间更新,求单点权值,区间求和、最值。

struct Tree{    #define lson L,mid,p<<1    #define rson mid+1,R,p<<1|1    #define family tree[p],tree[p<<1],tree[p<<1|1]    #define root 1,n,1    struct node{        int L,R;        int sum,add;        int Mx,Mn;    }tree[N<<2];    void Up(node &A,node L,node R){        A.sum=L.sum+R.sum;        A.Mx=max(L.Mx,R.Mx);        A.Mn=min(L.Mn,R.Mn);    }    void Down(node &A,node &L,node &R){        int &t=A.add;        if(!t)return;        L.add+=t;        R.add+=t;        L.sum+=t*(L.R-L.L+1);        R.sum+=t*(R.R-R.L+1);        t=0;    }    void build(int L,int R,int p){        tree[p].L=L,tree[p].R=R;        tree[p].sum=tree[p].add=0;        if(L==R){//          tree[p].sum=A[L];            return;        }        int mid=(L+R)>>1;        build(lson),build(rson);        Up(family);    }       void update_one(int x,int res,int p){        if(tree[p].L==tree[p].R){            tree[p].sum+=res;            return;        }        int mid=(tree[p].L+tree[p].R)>>1;        if(x<=mid)update_one(x,res,p<<1);        else update_one(x,res,p<<1|1);        Up(family);    }    void update_interval(int L,int R,int p,int res){        if(tree[p].L==L && tree[p].R==R){            tree[p].add+=res;            tree[p].sum+=1LL*res*(R-L+1);            return;        }        Down(family);        int mid=(tree[p].L+tree[p].R)>>1;        if(R<=mid)update_interval(L,R,p<<1,res);        else if(L>mid)update_interval(L,R,p<<1|1,res);        else update_interval(lson,res),update_interval(rson,res);        Up(family);    }    //注意求单点只需要沿途加上sum即可,不用Down     int query_one(int x,int p){        int mid=(tree[p].L+tree[p].R)>>1;        if(x<=mid)return tree[p].sum+query_one(x,p<<1);        else return tree[p].sum+query_one(x,p<<1|1);    }    int query_interval(int L,int R,int p){        if(tree[p].L==L && tree[p].R==R)return tree[p].sum;        Down(family);        int mid=(tree[p].L+tree[p].R)>>1;        if(R<=mid)return query_interval(L,R,p<<1);        else if(L>mid)return query_interval(L,R,p<<1|1);        else return query_interval(lson)+query_interval(rson);    }    int query_Max(int L,int R,int p){        if(tree[p].L==L && tree[p].R==R)return tree[p].Mx;        int mid=(tree[p].L+tree[p].R)>>1;        if(R<=mid)return query_Max(L,R,p<<1);        else if(L>mid)return query_Max(L,R,p<<1|1);        else return max(query_Max(lson),query_Max(rson));     }    int query_Min(int L,int R,int p){        if(tree[p].L==L && tree[p].R==R)return tree[p].Mn;        int mid=(tree[p].L+tree[p].R)>>1;        if(R<=mid)return query_Min(L,R,p<<1);        else if(L>mid)return query_Min(L,R,p<<1|1);        else return min(query_Min(lson),query_Min(rson));     }}Tree;

小结:
线段树是一个非常好用的东西,是常用于维护区间的某些值的数据结构之一。

原创粉丝点击