BIT树状数组

/*Binary indexed Tree
    给定初始值全为0的数列 A1,A2,A3……An
    1:给定i 求A1+A2+……+Ai
    2:给定i和  X求Ai+=  X;
*/
# include<stdio.h>
# define N 101
int SUM(int BIT[],int i)
{
    int sum=0;
    if(i>BIT[0]) i=BIT[0];
    while(i>0){
        sum+=BIT[i];
        i&=i-1;
      }
      return sum;
}
void ADD(int BIT[],int i,int x)
{
    while(i<=BIT[0]){
        BIT[i]+=x;
        i+=i&-i;
    }
}
int main(){
    int A[N]={0},i,t,j;
    freopen("haha.txt","r",stdin);
    scanf("%d ",&A[0]);
    for(i=1;i<=A[0];i++)
    {
        scanf("%d",&t);
        ADD(A,i,t);
        for(j=1;j<=A[0];j++)
        printf("%4d ",A[j]);
        printf("\n");
    }
    for(i=1;i<=15;i++)
        printf("%d\n",SUM(A,i));
    return 0;
}
/*Binary indexed Tree
    给定初始值全为0的数列 A1,A2,A3……An
    1:给定i 求A1+A2+……+Ai
    2:给定i和  X求Ai+=  X;
    给定N个元素的{Ai}数组,求对这N个元素进行冒泡排序的所需的交换次数 N∈[1,100000]
    冒泡排序是 一种 每次找到满足的Ai>Ai+1的i,并交换Ai和Ai+1 知道最后不存在这样的i的算法
    EG:输入N=4  A={3,1,4,2};
    输出 :3
    解:
    冒泡排序的复杂度为0(N^2) 显然不行 BIT 树状数组
    逆序数:
    i<j but AI>Aj的数对的个数
    对于每一个j 如果能快速求出满足次条件的逆序数的i的个数,那么问题就迎刃而解
    我们做如下操作:把j-(BIT[]查询所得到的前Aj的和加到答案中)
    把BIT的A[j]++
    对于每一个j,BIT[]查询所得到的Aj的前Aj项的和就是满足i<j ai<=aj的个数
    j再减去这个数 就是逆序数的个数
     对每一个J的操作都是0(logN)所以整个算法的复杂度0(NlogN);
*/
# include<stdio.h>
# define N 101
int A[N];
int SUM(int BIT[],int i)  //求前i项和
{
    int sum=0;
    if(i>BIT[0]) i=BIT[0];  //为了防止形参错误导致数组越界
    while(i>0){
        sum+=BIT[i];  //求SUM
        i&=i-1;  //移动i
      }
      return sum;
}
void ADD(int BIT[],int i,int x)  //把第i项改为BIT[i]+=x
{
    while(i&&i<=BIT[0]){
        BIT[i]+=x;
        i+=i&-i;
    }
}
int main(){
    long long sum=0;
    int i,t;
    //freopen("SSS.txt","r",stdin);
    scanf("%d ",&A[0]);
    for(i=1;i<=A[0];i++)
        scanf("%d",&A[i]);
    for(i=1;i<=A[0];i++)
    {
        sum+=i+1-SUM(A,A[i]+1);
        ADD(A,A[i]+1,1);
    }
    printf("%lld\n",sum);
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值