树状数组模板

树状数组还可以用来求区间异或和等与加法相同性质的操作

单点更新, 区间查询

相比于线段树, 好写的多
下标从1开始, sum(k)返回区间[1, k]的值, update将位置p的值+x
复杂度都是 O(logn) O ( l o g n )

int bit[maxn], n;
inline int lowbit(int x) { return x&(-x); }
inline void init(int n) { memset(bit, 0, sizeof(int) * (n+1)); }
int sum(int k)
{
    return k<=0 ? 0 : bit[k] + sum(k-lowbit(k));
}
void update(int p, int x)
{
    for( ; p<=n; p+=lowbit(p)) bit[p] += x;
}
inline int query(int l, int r) { return sum(r) - sum(l-1); }

区间修改, 单点查询

核心代码一模一样, 只是调用函数时候不同

int bit[maxn], n;
inline int lowbit(int x) { return x&(-x); }
inline void init(int n) { memset(bit, 0, sizeof(int) * (n+1)); }
int sum(int k)
{
    return k<=0 ? 0 : bit[k] + sum(k-lowbit(k));
}
void update(int p, int x)
{
    for( ; p<=n; p+=lowbit(p)) bit[p] += x;
}
//将区间[l, r]加v
update(l, v);
update(r+1, -v);
//查询点pos
sum(pos);

区间修改, 区间更新

利用一个二维树状数组实现区间更新, 复杂度都是 O(logn) O ( l o g n )

int bit0[MAXN], bit1[MAXN];
int n;

inline int lowbit(int x) { return x&(-x); }

int sum(int bit[], int k)
{
    return k<=0 ? 0 : bit[k] + sum(bit, k - lowbit(k));
}

void update(int bit[], int i, int x)
{
    for( ; i<=n; i+=lowbit(i)) bit[i] += x;
}

inline int query(int l, int r)
{
    return sum(bit0, r) - sum(bit0, l-1) + sum(bit1, r) * r - sum(bit1, l-1) * (l-1);
}

inline void update(int l, int r, int x)
{
    update(bit0, l, -x*(l-1));
    update(bit0, r+1, x*r);
    update(bit1, l, x);
    update(bit1, r+1, -x);
}

二维树状数组

单点更新, 区间查询

const int maxn = 2500 + 10, inf = 0x3f3f3f3f;
typedef unsigned long long ull;
ull bit[maxn][maxn];
int n;
inline int lowbit(int x) { return x&(-x); }
ull sum(int x, int y)
{
    ull s = 0;
    for(int i=x; i>0; i-=lowbit(i))
        for(int j=y; j>0; j-=lowbit(j))
            s += bit[i][j];
    return s;
}
void add(int x, int y, int v)
{
    for(int i=x; i<=maxn; i+=lowbit(i))
        for(int j=y; j<=maxn; j+=lowbit(j))
            bit[i][j] += v;
}
//查询(x1, y1), (x2, y2)
sum(x2, y2)-sum(x2, y1-1)-sum(x1-1 ,y2)+sum(x1-1, y1-1);
//修改(x,y)
add(x, y, v);

区间修改, 单点查询

//查询(x, y)
sum(x, y);
//改变(x1, y1)(x2, y2)全部加v
add(x1, y1, v);
add(x1, y2+1, -v);
add(x2+1, y1, -v);
add(x2+1, y2+1, v);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值