题解:SP9650 TRIPINV - Mega Inversions

双倍经验

建议先做 P1908 逆序对

可以想出,一个点所产生的逆序对数量就是右边比它小的,左边比它大的,相乘后,便是这个点所产生的逆序对数量。右边比它小的与左边比它大的数的个数可以用树状数组维护。

供上代码:(离散化方便过双倍经验)

# include <bits/stdc++.h>
# define lowbit(x) (x & (-x))
using namespace std;
int n , tot , a[1000010] , b[1000010] , l[1000010] , r[1000010];
long long sum , tr[1000010];
inline void add(int x , int w)
{
    while(x <= tot)
    {
        tr[x] += w;
        x += lowbit(x);
    }
    return ;
}
inline int query(int x)
{
    int sum = 0;
    while(x)
    {
        sum += tr[x];
        x -= lowbit(x);
    }
    return sum;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> n;
    for(int i = 1 ; i <= n ; i ++)
    {
        cin >> a[i];
        b[i] = a[i];
    }
    sort(b + 1 , b + n + 1);
    tot = unique(b + 1 , b + n + 1) - b - 1;
    for(int i = 1 ; i <= n ; i ++)
    {
        a[i] = lower_bound(b + 1 , b + tot + 1 , a[i]) - b;
        r[i] = query(tot) - query(a[i]);
        add(a[i] , 1);
    }
    memset(tr , 0 , sizeof tr);
    for(int i = n ; i >= 1 ; i --)
    {
        l[i] = query(a[i] - 1);
        add(a[i] , 1);
    }
    for(int i = 1 ; i <= n ; i ++) sum += 1LL * l[i] * r[i];
    cout << sum;
    return 0;
}
posted @ 2025-08-18 12:48  zhangyimin12345  阅读(7)  评论(0)    收藏  举报