加载中…

返回上一页

树状数组

树状数组,又名 ​​bit,是一类支持单点修改、查询前缀和的一类最基础的数据结构.

​​lowbit

取一个数二进制最后一位. 通常使用这个数二进制与它的相反数得到.

#define lowbit(x) (x&-x)

数组

ll c[maxn];

没了.

修改

每次加自身的 lowbit 直至加到要求的值(通常为 ​​n).

inline void update(rll x,rll v)
{
	for(rll i=x;i<=n;i+=lowbit(i))
		c[i]+=v;// 在 x 点加上 v
}

查询

每次减自身的 lowbit 直至 0,得到的答案为从 1x 的前缀和.

inline ll query(rll x)
{
	rll ans=0;
	for(rll i=x;i;i-=lowbit(i)) ans+=c[i];
	return ans;
}

由于是前缀和,要查询 ​​[l,r] 区间可以将 ans=query(r)-query(l-1).

标准模板

template<typename T,size_t siz>
class bit
{
#define lowbit(x) (x&-x)
private:
	T c[siz];
public:
	inline void upd(rg T x,rg T n,rg T v) { for(rg T i=x;i<=n;i+=lowbit(i)) c[i]+=v; }
	inline T query(rg T x) { rg T ans=0;for(rg T i=x;i;i-=lowbit(i)) ans+=c[i];return ans; }
#undef lowbit
};

bit<ll,maxn> t;

二维树状数组

就是把一维的换成二维的,外层修改查询和里层一样,也是使用 ​​lowbit.

利用差分实现区间修改、单点/区间查询

inline void add(rll l,rll r,rll v) //区间[l,r]加上x
{
    t.update(l,n,v); t.update(r+1,n,-v);
}
inline ll query(rll x) // 单点查询
{
    rll ans=0;
    for(rll i=x;i;i-=lowbit(i))  ans+=t.c[i];
    return ans;
}
template<typename T,size_t sz>
class bit
{
    T c[sz],c2[sz];
    inline void update(rg T x,rg T v)
    {
        for(rg T i=x;i<=n;i+=lowbit(i)) c[i]+=v,c2[i]+=v*x;
    }
    inline void add(rg T l,rg T r,rg T v) //区间[l,r]加上x
    {
        update(l,v); update(r+1,-v);
    }
    inline ll get(rg T x)
    {
        ll ans=0;
        for(rg T i=x;i;i-=lowbit(i)) ans+=(x+1)*c[i]-c2[i];
        return ans;
    }
    inline ll query(rg T l,rg T r) //区间查询
    {
        return get(r)-get(l-1);
    }
};
posted @ 2022-10-05 16:14  1Liu  阅读(3)  评论(0)    收藏  举报