You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

49 lines
1.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
const int N = 500010;
int n;
int a[N], q[N], ql;
// 二分模板 lower_bound (左闭右开)
int find(int x) {
return lower_bound(q + 1, q + 1 + ql, x) - q;
}
// 树状数组模板
typedef long long LL;
#define lowbit(x) (x & -x)
int c[N];
void add(int x, int d) {
for (int i = x; i < N; i += lowbit(i)) c[i] += d;
}
LL sum(int x) {
LL res = 0;
for (int i = x; i; i -= lowbit(i)) res += c[i];
return res;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), q[i] = a[i]; // 复制出来一份q[i],用于排序+去重=离散化数组
// 离散化 = 由小到大排序+去重
sort(q + 1, q + n + 1);
// 排序后,原数组原地去重,得到离散化后的数组
ql = 1;
for (int i = 2; i <= n; i++)
if (q[i] != q[ql]) q[++ql] = q[i];
LL res = 0;
for (int i = 1; i <= n; i++) { // 捋着原数组来
int x = find(a[i]); // 通过二分算法找到a[i]映射的 离散化后q[]数组中找到对应的新下标
// 由于数值排序是由小到大进行的,所以在我之前进入树状数组的,肯定是数值比我小的,同时,它们的位置还在我后面,就是逆序
res += sum(ql) - sum(x); // sum(bl)-sum(x):从[x+1~bl]这段区间内的元素个数数量,也就是在枚举到x这个数时已经产生的比x这个数大的有多少个
add(x, 1); // 下标为x的位置个数数量+1
}
// 输出结果
printf("%lld", res);
return 0;
}