题目:

珂朵莉给了你一个序列,有个子区间,求出她们各自的逆序对个数,然后加起来输出。
对于100%的数据,n <=1000000 ,0 <= 序列中每个数 <= 1000000000


做法:

换个角度,题目要我们求的是每个逆序对在多少个子区间内。那么对于一个逆序对,它的贡献就是理解为,任选一个位置任选一个位置区间是一个包含逆序对的子区间。
序列中第个位置作为第二个数的逆序对,就是在中找多少个比大的数。现在假如我们知道在中比大的数的位置和。那么第个位置作为第二个数的所有逆序对的子区间贡献就等于。这个我们离散化之后用线段树维护。问题就解决了。具体怎么维护的请看代码。
PS:这题数据爆longlong,用__int128可过。


代码:

#include <bits/stdc++.h>
#define lson (rt<<1)
#define rson (rt<<1|1)
#define debug(a) cout << #a ": " << a << endl
#define IOS ios::sync_with_stdio(false), cin.tie(0)
using namespace std;
typedef __int128 ll;
inline int read(void){
    char ch = getchar();
    int ans = 0;
    while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch)) ans = ans*10+ch-'0', ch = getchar();
    return ans;
}
const int N = 1e6 + 7;
int n, m, a[N], b[N];
vector<int> h;
ll T[N<<2];
int get(int x){
    return lower_bound(h.begin(), h.end(), x)-h.begin()+1;
}
void update(int pos, ll add, int l, int r, int rt){
    if (l == r){
        T[rt] += add; return;
    }
    int mid = (l+r) >> 1;
    if (pos <= mid) update(pos, add, l, mid, lson);
    else update(pos, add, mid+1, r, rson);
    T[rt] = T[lson]+T[rson];
}
ll query(int L, int R, int l, int r, int rt){
    if (L > R) return 0;
    if (L <= l && r <= R){
        return T[rt];
    }
    int mid = (l+r) >> 1;
    ll ans = 0;
    if (L <= mid){
        ans += query(L, R, l, mid, lson);
    }
    if (R > mid){
        ans += query(L, R, mid+1, r, rson);
    }
    return ans;
}
void Print(ll x){
    if (x == 0) return;
    Print(x/10);
    int dig = x%10;
    printf("%d", dig);
}
int main(void){
    n = read();
    for (int i = 1; i <= n; ++i){
        a[i] = read();
        h.push_back(a[i]);
    }
    sort(h.begin(), h.end());
    h.erase(unique(h.begin(), h.end()), h.end());
    m = h.size();
    for (int i = 1; i <= n; ++i){
        a[i] = get(a[i]);
        b[i] = i;
    }
    ll ans = 0;
    for (int i = 1; i <= n; ++i){
        ll lef = query(a[i]+1, m, 1, m, 1);
        ll rig = n-i+1;
        ans += lef*rig;
        update(a[i], b[i], 1, m, 1);
    }
    if (ans == 0) printf("0\n");
    else Print(ans);
    return 0;
}