您的位置:首页 > 其它

树状数组的应用(区间修改,区间查询,多维树状数组)

2017-08-03 09:32 477 查看
14、树状数组
(1)、单点增减+区间求和
思路:C[x]表示该点的元素:sum(x)=C[1]+C[2]+……C[x]

[cpp] view
plain copy

 print?

int arr[MAXN];  

inline int sum(int x){int res=0;while(x)res+=arr[x],x-=lowbit(x);return res;}  

inline void add(int x,int n){while(x<MAXN)arr[x]+=n,x+=lowbit(x);}  

inline int query(int x,int y){return sum(y)-sum(x-1);}  

(2)、区间增减+单点查询
思路:C[x]表示该点元素与左边元素的差值:num[x]=C[1]+C[2]+……C[x]

[cpp] view
plain copy

 print?

int arr[MAXN]  

inline int sum(int x){int res=0;while(x)res+=arr[x],x-=lowbit(x);return res;}  

inline void add(int x,int n){while(x<MAXN)arr[x]+=n,x+=lowbit(x);}  

inline int update(int x,int y,int n){add(x,n);add(y+1,-n);}  

(3)、区间增减+区间查询
思路:C1[x]表示该点元素与左边的差值,C2[x]表示的是x*C[x]

[cpp] view
plain copy

 print?

sum(sum(C[j],j<=i)i<=x)  

= x*C[1]+(x-1)*C[2]+……+C[x]  

=(x+1)*sum(C[i],i<=x)-sum(i*C[i],i<=x);  

则可以想到用C1[x]维护C[x]的值,C2[x]维护x*C[X]的值

[cpp] view
plain copy

 print?

template <typename X>  

struct tree_array{  

    struct tree_array_single{  

        X arr[MAXN];  

        void add(int x,X n){while(x<=N)arr[x]+=n,x+=lowbit(x);}  

        X sum(int x){X sum=0;while(x)sum+=arr[x],x-=lowbit(x);return sum;}  

    }T1,T2;  

    void reset(){CLR(T1.arr,0); CLR(T2.arr,0);}  

    void add(int x,X n){T1.add(x,n);T2.add(x,x*n);}  

    void update(int L,int R,int n){add(L,n);add(R+1,-n);}  

    X sum(int x){return (x+1)*T1.sum(x)-T2.sum(x);}  

    X query(int L,int R){return sum(R)-sum(L-1);}  

};  

15、多维树状数组
①单点增减(add) + 矩形求和(query) 
②矩形增减(update) + 单点求值(sum)

[cpp] view
plain copy

 print?

int arr[MAXN][MAXN]  

inline void add(int x,int y,int n) {  

    for(int i=x;i<MAXN;i+=lowbit(i))  

        for(int j=y;j<MAXN;j+=lowbit(j))  

            arr[i][j]+=n;  

}  

inline int sum(int x,int y){  

    int res=0;  

    for(int i=x;i;i-=lowbit(i))  

        for(int j=y;j;j-=lowbit(j))  

            res+=arr[i][j];  

    return res;  

}  

inline int query(int L,int B,int R,int T) {  

    return sum(R,T)+sum(L-1,B-1)-sum(R,B-1)-sum(L-1,T);  

}  

inline void update(int L,int B,int R,int T,int n){  

    update(L,B,n);update(L,T+1,n);update(R+1,B,n);update(R+1,T+1,n);  

}  

③矩形增减(update)+ 矩形求和(query)

[cpp] view
plain copy

 print?

template<typename X>  

class tree_array{  

    struct tree_array_single{  

        X arr[MAXN][MAXN];  

        void add(int x,int y,X n){  

            for(int i=x; i<MAXN; i+=lowbit(i))  

                for(int j=y; j<MAXN; j+=lowbit(j))  

                    arr[i][j]+=n;  

        }  

        X sum(int x,int y){  

            X res=0;  

            for(int i=x; i; i-=lowbit(i))  

                for(int j=y; j; j-=lowbit(j))  

                    res+=arr[i][j];  

            return res;  

        }  

    } T1,T2,T3,T4;  

    void add(int x,int y,int n){  

        T1.add(x,y,n);T2.add(x,y,y*n);T3.add(x,y,x*n);T4.add(x,y,x*y*n);  

    }  

    X sum(int x,int y){  

    return (x+1)*(y+1)*T1.sum(x,y)-(x+1)*T2.sum(x,y)-(y+1)*T3.sum(x,y)+T4.sum(x,y);}  

public:  

    void init(){CLR(T1.arr,0);CLR(T2.arr,0);CLR(T3.arr,0);CLR(T4.arr,0);}  

    void update(int L,int B,int R,int T,int n){  

        add(L,B,n);add(L,T+1,-n);add(R+1,B,-n);add(R+1,T+1,n);  

    }  

    X query(int L,int B,int R,int T){  

        return sum(R,T)-sum(L-1,T)-sum(R,B-1)+sum(L-1,B-1);  

    }  

};  

④单点增减(add) + 立方体求和(query)
⑤立方体增减(update) + 单点求值(sum)

[cpp] view
plain copy

 print?

int arr[MAXN][MAXN][MAXN];  

inline int sum(int x,int y,int z){  

    int res=0;  

    for(int i=x;i;i-=lowbit(i))  

        for(int j=y;j;j-=lowbit(j))  

            for(int k=z;k;k-=lowbit(k))  

                res^=arr[i][j][k];  

    return res;  

}  

inline void add(int x,int y,int z,int n){   

    for(int i=x;i<MAXN;i+=lowbit(i))  

        for(int j=y;j<MAXN;j+=lowbit(j))  

            for(int k=z;k<MAXN;k+=lowbit(k))  

                arr[i][j][k]+=n;  

}  

inline void update(int x1,int y1,int z1,int x2,int y2,int z2,int n){  

add(x1,y1,z1,n);  

add(x2+1,y1,z1,-n);add(x1,y2+1,z1,-n);add(x1,y1,z2+1,-n);  

add(x2+1,y2+1,z1,n);add(x2+1,y1,z2+1,n);add(x1,y2+1,z2+1,n);  

add(x2+1,y2+1,z2+1,-n);  

}  

inline int query(int x1,int y1,int z1,int x2,int y2,int z2){  

    return sum(x2,y2,z2)  

    -sum(x2,y2,z1-1)-sum(x2,y1-1,z2)-sum(x1-1,y2,z2)  

    +sum(x2,y1-1,z1-1)+sum(x1-1,y2,z1-1)+sum(x1-1,y1-1,z2)  

    -sum(x1-1,y1-1,z1-1);  

}  

⑥立方体增减(update) + 立方体求和(query)///随便写写……复杂度较高

[cpp] view
plain copy

 print?

template<typename X>  

class tree_array_Cube{  

    struct tree_array_single{  

        X arr[MAXN][MAXN][MAXN];  

        X sum(int x,int y,int z){  

            X res=0;  

            for(int i=x;i;i-=lowbit(i))  

                for(int j=y;j;j-=lowbit(j))  

                    for(int k=z;k;k-=lowbit(k))  

                        res+=arr[i][j][k];  

            return res;  

        }  

        void add(int x,int y,int z,X n){  

            for(int i=x;i<MAXN;i+=lowbit(i))  

                for(int j=y;j<MAXN;j+=lowbit(j))  

                    for(int k=z;k<MAXN;k+=lowbit(k))  

                        arr[i][j][k]+=n;  

        }  

    }T1,T2,T3,T4,T5,T6,T7,T8;  

    void add(int x,int y,int z,X n){  

        T1.add(x,y,z,n);  

        T2.add(x,y,z,x*n);T3.add(x,y,z,y*n);T4.add(x,y,z,z*n);  

        T5.add(x,y,z,x*y*n);T6.add(x,y,z,y*z*n);T7.add(x,y,z,x*z*n);  

        T8.add(x,y,z,x*y*z*n);  

    }  

    X sum(int x,int y,int z){  

        return (x+1)*(y+1)*(z+1)*T1.sum(x,y,z)  

        -(y+1)*(z+1)*T2.sum(x,y,z)-(x+1)*(z+1)*T3.sum(x,y,z)-(x+1)*(y+1)*T4.sum(x,y,z)  

        +(z+1)*T5.sum(x,y,z)+(x+1)*T6.sum(x,y,z)+(y+1)*T7.sum(x,y,z)-T8.sum(x,y,z);  

    }  

public:  

    void init(){  

        CLR(T1.arr,0);CLR(T2.arr,0);CLR(T3.arr,0);CLR(T4.arr,0);  

        CLR(T5.arr,0);CLR(T6.arr,0);CLR(T7.arr,0);CLR(T8.arr,0);  

    }  

    void update(int x1,int y1,int z1,int x2,int y2,int z2,X n){  

        add(x1,y1,z1,n);  

        add(x2+1,y1,z1,-n);add(x1,y2+1,z1,-n); add(x1,y1,z2+1,-n);  

        add(x2+1,y2+1,z1,n);add(x2+1,y1,z2+1,n);add(x1,y2+1,z2+1,n);  

        add(x2+1,y2+1,z2+1,-n);  

    }  

    X query(int x1,int y1,int z1,int x2,int y2,int z2){  

        return sum(x2,y2,z2)  

        -sum(x2,y2,z1-1)-sum(x2,y1-1,z2)-sum(x1-1,y2,z2)  

        +sum(x2,y1-1,z1-1)+sum(x1-1,y2,z1-1)+sum(x1-1,y1-1,z2)  

        -sum(x1-1,y1-1,z1-1);  

    }  

};  

16、树状数组—区间最大值

[cpp] view
plain copy

 print?

inline void init()  

{  

    CLR(arr,0);  

    for(int i=1;i<=N;++i)  

        for(int j=i;j<=N&&arr[j]<num[i];j+=lowbit(j))  

            arr[j]=num[i];  

}  

inline int query(int L,int R)  

{  

    int res=0;  

    for(--L;L<R;){  

        if(R-lowbit(R)>=L){res=max(res,arr[R]);R-=lowbit(R);}  

        else{res=max(res,num[R]);--R;}  

    }  

    return res;  

}  

inline void update(int x,int val)  

{  

    int ori=num[x];  

    num[x]=val;  

    if(val>=ori)  

        for(int i=x;i<=N&&arr[i]<val;i+=lowbit(i))  

            arr[i]=val;  

    else{  

        for(int i=x;i<=N&&arr[i]==ori;i+=lowbit(i))  

        {  

            arr[i]=val;  

            for(int j=lowbit(i)>>1;j;j>>=1)  

                arr[i]=max(arr[i],arr[i-j]);  

        }  

    }  

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐