树状数组
树状数组,又名 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,得到的答案为从 1 到 x 的前缀和.
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);
}
};
--END--

浙公网安备 33010602011771号
我的博客: 𝟷𝙻𝚒𝚞
本文链接: https://www.cnblogs.com/1Liu/articles/16755751.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!