树状数组详解

一 定义

 树状数组是一种数据结构,支持区间内的查询,单点修改,区间修改等的一种数据结构,虽然支持的功能较线段树较少,但是它具有代码量少,逻辑清晰等优势

二 原理

 对于树状数组,首先我们有一个原数组a[30], 然后我们有一个BIT数组tree[30],对于每一个数字,我们都能得到它的二进制表达,基于这个二进制表示,每个数都负责了一个区间内的数,如tree[4]负责的是1 2 3 4 四个数的区间,tree[3] 负责的是 3 这个数。

三 代码实现

l o w b i t ( x ) 返 回 的 是 x 中 最 近 的 一 个 1 lowbit(x)返回的是x中最近的一个1 lowbit(x)x1

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

u p d a t e ( x ) 是 对 x 这 个 位 置 上 的 数 进 行 修 改 update(x)是对x这个位置上的数进行修改 update(x)x

inline void update(ll x,int p)
{
    for (ll i = x; i <= n; i += lowbit(i))
    tree[i] += p;
}

f i n d ( x ) 寻 找 的 是 这 个 位 置 到 之 前 的 数 的 区 间 内 的 所 有 和 find(x)寻找的是这个位置到之前的数的区间内的所有和 find(x)

inline int find(ll x)
{
    int sum = 0;
    for (ll i = x; i > 0; i -= lowbit(i))
    sum += tree[i];
    return sum;
}

四 逆序对

模版题 逆序对其实就是求在一一个数组内,有多少组数字,满足序列的大小关系和数字的大小关系是相反的。

1.解题思路

 首先我们对一个这个数组进行离散话,将里面的数字之间的大小关系转化为相对的大小关系,然后再对他按照大小的顺序进行排列,然后再这个大小的顺序,将每一个数的序号存入这个树状数组内,更新树状数组内比这个数大的数之和。当我们进行find操作时,得到的是比这个数小的数的数目之和。所以i - find(x)得到的是这个数字的逆序对的数目,从1 ~ n求和即可

2 代码
#include<iostream>
#define N 500
#define ll long long
using namespace std;
ll bit[N],Rank[N],ans,n;
struct point
{
    int num;
    int value;
}f[N];
ll lowbit(ll x){return x&-x;}
inline void update(ll num,ll i)
{
    for(;num <= n;num+=lowbit(num)) bit[num]+=i;
}
inline int cmp(point a, point b)
{
    if(a.value==b.value) return a.num < b.num;
    else return a.value < b.value;
}
inline ll ask(ll p)
{
    ll sum = 0;
    for(;p;p-=lowbit(p))sum+=bit[p];
    return sum;
}
int main()
{
    scanf("%lld",&n);
    for(int i = 1;i <= n;i++)
    {
        scanf("%d",&f[i].value);
        f[i].num = i;
    }
    sort(f+1,f+1+n,cmp);
    for(ll i = 1;i<= n;i++) Rank[f[i].num] = i;
    for(int i=1;i<=n;i++)
    {
        update(Rank[i],1);
        ans+=i-ask(Rank[i]);
    }
    printf("%lld",ans);
    return 0;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值