树状数组

来源:互联网 发布:silk mobile python 编辑:程序博客网 时间:2024/05/16 04:32
核心代码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 longll 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;}

0 0