珂朵莉的数列 - 逆序对

题目描述

珂朵莉给了你一个序列,有(n*(n+1))/2个子区间,求出她们各自的逆序对个数,然后加起来输出。


对于每个区间,其贡献为(n-i+1)*SUM.
SUM = 前面插入arr[k]值大于当前值的下标k的和
因为对一个区间来说其贡献为(n-i+1)*l,一个是右界,一个是左界,而左界的和即为上面的SUM。

//
// Created by SANZONG on 2021/7/7.
//

#include "bits/stdc++.h"
using namespace std;
const int maxn = 1e6+10;
int arr[maxn];
int cp[maxn];
int n;
long long t[maxn];
int lowerbit(int x)
{
    
    
    return x&(-x);
}

void update(int p,int i)
{
    
    
    while (p <= n)
    {
    
    
        t[p]+=i;
        p += lowerbit(p);
    }
}
__int128 getsum(int p)
{
    
    
    __int128  res = 0;
    while (p > 0)
    {
    
    
        res += t[p];
        p -= lowerbit(p);
    }
    return res;
}
void print(__int128 x)
{
    
    
    if(!x)
    {
    
    
        puts("0");
        return ;
    }
    string ret="";
    while(x)
    {
    
    
        ret+=x%10+'0';
        x/=10;
    }
    reverse(ret.begin(),ret.end());
    cout<<ret<<endl;
}
signed main()
{
    
    
    cin >> n;
    for (int i = 1; i <= n; ++i) {
    
    
        cin >> arr[i];
        cp[i] = arr[i];
    }
    sort(cp+1,cp+1+n);
    for (int i = 1; i <= n; ++i) {
    
    
        arr[i] = lower_bound(cp+1,cp+1+n,arr[i])-cp;
    }
    __int128 ans = 0;
    for (int i = 1; i <= n; ++i) {
    
    
        ans += (n-i+1)*(getsum(n) - getsum(arr[i]));
        update(arr[i],i);
    }
    print(ans);

}

猜你喜欢

转载自blog.csdn.net/weixin_45509601/article/details/118539692