cal (树状数组)

来源:互联网 发布:淘宝哪家香水是假货 编辑:程序博客网 时间:2024/05/17 08:33

cal

思路:
转化成考虑每个点的贡献,一个点的贡献存在于左边比它小的数和右边比它大的数的任意组合,所以一个点的贡献就是左边比它小的数的个数和右边比它大的数的个数的乘积,树状数组维护。

#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#define N 300005using namespace std;int n, aa[N], b[N], c[N], f[N], g[N];long long ans;void add(int x){    for(int i=x;i<=n;i+=i&-i)        c[i]++;}int query(int x){    int rt=0;    for(int i=x;i;i-=i&-i)        rt+=c[i];    return rt;}int main(){    scanf("%d", &n);    for(int i=1; i<=n; i++){        scanf("%d", &aa[i]);        b[i] = aa[i];    }    sort(b+1, b+n+1);    for(int i=1; i<=n; i++)        aa[i] = lower_bound(b+1, b+n+1, aa[i]) - b;    for(int i=1; i<=n; i++){        f[i] = n - aa[i] - (query(n) - query(aa[i]));        add( aa[i] );//右边比它大的数的个数 等于 比它大的数的个数减去左边比它大的数个个数     }    memset(c, 0, sizeof(c));    ans = 0;    for(int i=1; i<=n; i++){        g[i] = query(aa[i]);//左边比它小的数的个数         add( aa[i] );        ans += (1LL * g[i] * f[i]);    }    cout << ans << endl;    return 0; }