C++树状数组入门模板+例题逆序对

若是想学习 数组树状区间操作+区间和 模板题的同学可以直接点击链接

树状数组,是一个用于在近似 O(logn)时间内动态修改以及查询前缀和的数据结构
我们以16为例子,把抽象的二进制过程画图具体化
在这里插入图片描述
函数lowbit()
我们可以观察到每一个数的下标加上它的二进制最低位等于上一层的下标,我们可以知道x&-x可以取到它的二进制最低位,
函数add()
运用配合函数lowbit()、运用前缀和
函数sum()
求1-i的和,对数组tree[i]逆向减lowbit()求和

该模板有区间修改和区间求和

 #include<bits/stdc++.h>
using namespace std;
const int MAX=50005;
int a[MAX],tree[MAX],n;
int lowbit(int x)  //找最低位的1 
{
	return x&-x;
}
void add(int i,int x)//修改数据在i加x 
{
    while(i<=n)
    {
        tree[i]+=x;
        i+=lowbit(i);
    }
}

int sum(int i)
{
    int s=0;
    while(i>0)
    {
        s+=tree[i];
        i-=lowbit(i);
    }
    return s;
}
void range_add(int l, int r, int a) //区间修改
    {
        add(l, a);
        add(r + 1, -a);
    }
ll range_sum(int l, int r)  //区间求和
    {
        return sum(r) - sum(l - 1);
    }

int main()
{
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	
	
	
 } 

例题
树状数组入门应用求 逆序对 (求数组右边比它小的个数和)
每次加入一个数x,判断x~MAX中存在多少个数,也就是在加入x前判断前面出现多少次比x大的数的个数。
力扣 315. 计算右侧小于当前元素的个数
codeforces 180. Inversions
牛客 逆序数

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define endl '\n'
#define ll long long 
using namespace std;
ll tree[100001],n,m;
ll lowbit(ll x)
{
	return x&-x;	
} 
void add(ll i,ll x)
{
	while(i<=100000)
	{
		tree[i]+=x;
		i+=lowbit(i);
	}
}
ll sum(ll i)
{
	ll res=0;
	while(i>0)
	{
		res+=tree[i];
		i-=lowbit(i);
	}
	return res;	
}
ll range_sum(ll l,ll r)
{
	return sum(r)-sum(l-1);
}
int main()
{
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
  	cin>>n;
  	ll ans=0;
  	for(int i=1;i<=n;i++)
  	{
  		cin>>m;
  		ans+=range_sum(m,100000);
		add(m,1);
	}
	cout<<ans;
    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值