模板整合

一、树状数组

1.简介

树状数组,支持区间查询和区间修改

2.使用方法

声明 :binary_tree 对象名称
node :树状数组的数据类型
SIZE :数据范围
build(初始数组,数组长度) :初始化操作,为元素赋初值
update(left,right,value) :将 \([left,right]\) 内的元素都增加 \(value\)
query(left,right) :求 \([left,right]\) 区间内的元素和

3.代码

class binary_tree
{
    #define node long long
    #define SIZE 100000
    public:
        inline node query(int x,int y) {return (y+1)*sum(tree1,y)-sum(tree2,y)-x*sum(tree1,x-1)+sum(tree2,x-1);}
        inline void build(node a[],int n)
        {
            tot=n; memset(tree1,0,sizeof(tree1)); memset(tree2,0,sizeof(tree2));
            for(register int i=1;i<=tot;i++) modify(i,a[i]-a[i-1]);
        }
        inline void update(node x,node y,node k) {modify(x,k); modify(y+1,-k);}
    private:
        node tree1[SIZE+1],tree2[SIZE+1],tot;
        inline node lowbit(node x) {return x&(-x);}
        inline node sum(node a[],node x) {node ans=0; while(x>0) {ans+=a[x]; x-=lowbit(x);} return ans;}
        inline void modify(node x,node k) {for(register node i=x;i<=tot;i+=lowbit(i)) {tree1[i]+=k; tree2[i]+=k*x;}}
    #undef node
    #undef SIZE
};

二、静态主席树

1.简介

主席树,支持查询区间第\(k\)

2.使用方法

声明 :president_tree 对象名称
node :树状数组的数据类型
SIZE :数据范围
build(初始数组,数组长度) :初始化操作,将数组进行离散化,为元素赋初值
query(left,right,rank) :求 \([left,right]\) 区间内的第\(rank\)

3.代码

class president_tree
{
    #define node int
    #define mid ((l+r)>>1)
    #define fm(x) memset(x,0,sizeof(x))
    #define SIZE 200000
    public:
        node query(int x,int y,int w) {return rank[_query(root[x-1],root[y],1,_size,w)];}
        void build(int a[],int n)
        {
            tot=0; fm(rank); fm(root); fm(sum); fm(L); fm(R);
            for(register int i=1;i<=n;i++) rank[i]=a[i];
            sort(rank+1,rank+n+1);
            _size=unique(rank+1,rank+n+1)-rank-1;
            root[0]=_build(1,_size);
            for(register int i=1;i<=n;i++)
                root[i]=update(root[i-1],1,_size,lower_bound(rank+1,rank+_size+1,a[i])-rank);
        }
    private:
        int tot,_size;
        node rank[SIZE+1],root[SIZE+1],sum[(SIZE<<5)+1],L[(SIZE<<5)+1],R[(SIZE<<5)+1];;
        node _build(int l,int r)
        {
            int k=++tot; sum[k]=0;
            if(l<r)
            {
                L[k]=_build(l,mid);
                R[k]=_build(mid+1,r);
            }
            return k;
        }
        node update(int pre,int l,int r,int w)
        {
            int k=++tot; L[k]=L[pre]; R[k]=R[pre]; sum[k]=sum[pre]+1;
            if(l<r)
                if(w<=mid) L[k]=update(L[pre],l,mid,w);
                else R[k]=update(R[pre],mid+1,r,w);
            return k;
        }
        node _query(int u,int v,int l,int r,int k)
        {
            if(l>=r) return l;
            int w=sum[L[v]]-sum[L[u]];
            if(w>=k) return _query(L[u],L[v],l,mid,k);
            else return _query(R[u],R[v],mid+1,r,k-w);
        }
    #undef node
    #undef mid
    #undef fm
    #undef SIZE
};

三、线段树

1.简介

线段树,支持区间修改和区间查询区间和

2.使用方法

声明 :segment_tree 对象名称
node :树状数组的数据类型
SIZE :数据范围
build(初始数组,数组长度) :初始化操作,为元素赋初值
update(left,right,value) :将 \([left,right]\) 内的元素都增加 \(value\)
query(left,right) :求 \([left,right]\) 区间内的元素和

3.代码

class segment_tree
{
    #define SIZE 100010
    #define node long long
    #define ls k<<1
    #define rs k<<1 | 1
    #define mid ((l+r)>>1)
    public:
        void build(int a[],int n) {_build(a,1,1,n); tot=n;}
        void update(int x,int y,int k) {_update(1,1,tot,x,y,k);}
        node query(int x,int y) {return _query(1,1,tot,x,y);}
        void clear() {tot=0; memset(sum,0,sizeof(sum)); memset(v,0,sizeof(v));}
    private:
        node sum[(SIZE<<2)+1],v[(SIZE)<<2+1]; int tot;
        void pushup(int k) {sum[k]=sum[ls]+sum[rs];}
        void pushdown(int k,int l,int r)
        {
            v[ls]+=v[k]; v[rs]+=v[k];
            sum[ls]+=(mid-l+1)*v[k];
            sum[rs]+=(r-mid)*v[k];
            v[k]=0;
        }
        void _update(int k,int l,int r,int ql,int qr,int u)
        {
            if(ql<=l && r<=qr)
            {
                sum[k]+=u*(r-l+1);
                v[k]+=u; return;
            }
            if(v[k]) pushdown(k,l,r);
            if(ql<=mid) _update(ls,l,mid,ql,qr,u);
            if(qr>mid) _update(rs,mid+1,r,ql,qr,u);
            pushup(k);
        }
        node _query(int k,int l,int r,int ql,int qr)
        {
            if(ql<=l && r<=qr) return sum[k];
            long long ans=0;
            if(v[k]) pushdown(k,l,r);
            if(ql<=mid) ans+=_query(ls,l,mid,ql,qr);
            if(qr>mid) ans+=_query(rs,mid+1,r,ql,qr);
            return ans;
        }
        void _build(int a[],int k,int l,int r)
        {
            if(l==r) {sum[k]=a[l]; return;}
            _build(a,ls,l,mid); _build(a,rs,mid+1,r);
            pushup(k);
        }
    #undef SIZE
    #undef node
    #undef ls
    #undef rs
    #undef mid
};
posted @ 2019-02-17 22:32  常青藤的花语  阅读(219)  评论(0编辑  收藏  举报

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。