首页 > 其他 > 详细

树状树组

时间:2019-04-27 16:24:52      阅读:138      评论:0      收藏:0      [点我收藏+]

这里丢一篇很好的blogs

https://www.cnblogs.com/hsd-/p/6139376.html

其实树状数组的是实现是根据二进制的

主要的函数有这三个

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

这个是返回原数上去除末尾一个1的数

such as 

  1. t=6(0110)
  2. -t=-6=(1001+1)=(1010)
  3. t&(-t)=(0010)=2 得到这个有什么用呢,继续看
    现在定义每一列的顶端结点C[]数组 
   如下图
 技术分享图片
 
   C[i]代表 子树的叶子结点的权值之和// 这里以求和举例
   如图可以知道
   C[1]=A[1];
   C[2]=A[1]+A[2];
   C[3]=A[3];
   C[4]=A[1]+A[2]+A[3]+A[4];
   C[5]=A[5];
   C[6]=A[5]+A[6];
   C[7]=A[7];
   C[8]=A[1]+A[2]+A[3]+A[4]+A[5]+A[6]+A[7]+A[8];
将C[]数组的结点序号转化为二进制
1=(001)      C[1]=A[1];
2=(010)      C[2]=A[1]+A[2];
3=(011)      C[3]=A[3];
4=(100)      C[4]=A[1]+A[2]+A[3]+A[4];
5=(101)      C[5]=A[5];
6=(110)      C[6]=A[5]+A[6];
7=(111)      C[7]=A[7];
8=(1000)    C[8]=A[1]+A[2]+A[3]+A[4]+A[5]+A[6]+A[7]+A[8];
对照式子可以发现  C[i]=A[i-2^k+1]+A[i-2^k+2]+......A[i]; (k为i的二进制中从最低位到高位连续零的长度)例如i=8时,k=3; 
举个例子 i=7;
sum[7]=A[1]+A[2]+A[3]+A[4]+A[5]+A[6]+A[7] ;   //前i项和
C[4]=A[1]+A[2]+A[3]+A[4];   C[6]=A[5]+A[6];   C[7]=A[7];
可以推出:   sum[7]=C[4]+C[6]+C[7];
序号写为二进制: sum[(111)]=C[(100)]+C[(110)]+C[(111)];
 
再举个例子 i=5
sum[7]=A[1]+A[2]+A[3]+A[4]+A[5] ;   前i项和
C[4]=A[1]+A[2]+A[3]+A[4];   C[5]=A[5];
可以推出:   sum[5]=C[4]+C[5];
序号写为二进制: sum[(101)]=C[(100)]+C[(101)];

所以说我们可以通过对i加减lowbit(i),就能实现得到111 110 100 000这样的数

int add(int i,int x)
{
    while (i<=n)
    {
        c[i]+=x;
        i+=lowbit(i);
    }
}

这个呢是树状数组实现单点修改

 1 int sum(int i)
 2 {
 3     int res=0;
 4     while (i>=1)
 5     {
 6         res+=c[i];
 7         i-=lowbit(i);
 8     }
 9     return res;
10 }

这个是实现区间求和查询跟上面的是一样的意识

 

 

 

树状数组求逆序对

#include<iostream>
#include<algorithm>
using namespace std;
struct sb
{
    int z,num;
}t[1001];
int c[1001],n;
bool cmp(sb a,sb b)
{
    return a.z<b.z?true:false;
}
int lowbit(int x)
{
    return x&(-x);
}
int add(int i,int x)
{
    while (i<=n)
    {
        c[i]+=x;
        i+=lowbit(i);
    }
}
int sum(int i)
{
    int res=0;
    while (i>=1)
    {
        res+=c[i];
        i-=lowbit(i);
    }
    return res;
}
int main ()
{
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        cin>>t[i].z;
        t[i].num=i;
    }
    sort(t+1,t+1+n,cmp);
    int ans=0;
    for (int i=1;i<=n;i++)
    {
        add(t[i].num,1);
        ans+=i-sum(t[i].num);
    }
    cout<<ans;
} 

 

树状树组

原文:https://www.cnblogs.com/zjzjzj/p/10778816.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!