树状数组

本文介绍了一种高效的数据结构——树状数组,并通过一个示例程序详细展示了如何使用树状数组进行区间求和计算。该程序首先读取一组整数,然后计算每个位置左侧元素的累计数量以及右侧元素的累计数量,最终输出特定条件下的区间和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

核心代码
ll sum(ll i){
    ll s = 0;
    while(i > 0){
        s += c[i];
        i -= i & -i;
    }
    return s;
}
ll add(ll i, ll x){
    while(i <= n){
        c[i] += x;
        i += i & -i;
    }
}

sum 子函数可以 求出前i项和,  add子函数 可以求出 把x加到i项


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define ll long long
ll c[100010];
ll left_[100010];
ll right_[100010];
ll vis[100010];
ll n;
ll sum(ll i){
    ll s = 0;
    while(i > 0){
        s += vis[i];
        i -= i & -i;
    }
    return s;
}
ll add(ll i, ll x){
    while(i <= 100010){
        vis[i] ++;
        i += i & -i;
    }
}
int main (){
    ll num;
    scanf("%lld",&num);
    while(num--){
        scanf("%lld",&n);
        memset(vis,0,sizeof(vis));
        memset(vis,0,sizeof(left_));
        memset(vis,0,sizeof(right_));
        memset(vis,0,sizeof(c));
        for(ll i = 1; i <= n; i++){
            scanf("%lld",&c[i]);
        }
        for(ll i = 1 ; i <= n ; i++){
            left_[i] = sum(c[i]);
            add(c[i],1);
        }
        memset(vis,0,sizeof(vis));
        for(ll i = n; i >= 1 ; i--){
            right_[i] = sum(c[i]);
            add(c[i],1);
        }
        ll sum = 0;
        for(ll i = 1; i <= n; i++){
            sum += (ll)(n - i - right_[i])*left_[i] + (ll)(i - left_[i] - 1)*right_[i];
        }
        printf("%lld\n",sum);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值